report.html

Report generated on 15-Jan-2026 at 16:35:06 by pytest-html v2.0.1

Summary

3 tests ran in 4.04 seconds.

0 passed, 0 skipped, 3 failed, 0 errors, 0 expected failures, 0 unexpected passes, 0 rerun

Results

Result Test Duration Links
Failed FOrUS_testing.py::FOrusWebsite::test_all_links 0.16
args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
> completed_proc = subprocess.run(args, capture_output=True)

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:116:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.10/subprocess.py:503: in run
with Popen(*popenargs, **kwargs) as process:
/usr/lib/python3.10/subprocess.py:971: in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <Popen: returncode: None args: ['/usr/local/lib/python3.10/dist-packages/sel...>
args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]
executable = b'/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager'
preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None
startupinfo = None, creationflags = 0, shell = False, p2cread = -1
p2cwrite = -1, c2pread = 15, c2pwrite = 18, errread = 19, errwrite = 20
restore_signals = True, gid = None, gids = None, uid = None, umask = -1
start_new_session = False

def _execute_child(self, args, executable, preexec_fn, close_fds,
pass_fds, cwd, env,
startupinfo, creationflags, shell,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite,
restore_signals,
gid, gids, uid, umask,
start_new_session):
"""Execute program (POSIX version)"""

if isinstance(args, (str, bytes)):
args = [args]
elif isinstance(args, os.PathLike):
if shell:
raise TypeError('path-like args is not allowed when '
'shell is true')
args = [args]
else:
args = list(args)

if shell:
# On Android the default shell is at '/system/bin/sh'.
unix_shell = ('/system/bin/sh' if
hasattr(sys, 'getandroidapilevel') else '/bin/sh')
args = [unix_shell, "-c"] + args
if executable:
args[0] = executable

if executable is None:
executable = args[0]

sys.audit("subprocess.Popen", executable, args, cwd, env)

if (_USE_POSIX_SPAWN
and os.path.dirname(executable)
and preexec_fn is None
and not close_fds
and not pass_fds
and cwd is None
and (p2cread == -1 or p2cread > 2)
and (c2pwrite == -1 or c2pwrite > 2)
and (errwrite == -1 or errwrite > 2)
and not start_new_session
and gid is None
and gids is None
and uid is None
and umask < 0):
self._posix_spawn(args, executable, env, restore_signals,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite)
return

orig_executable = executable

# For transferring possible exec failure from child to parent.
# Data format: "exception name:hex errno:description"
# Pickle is not used; it is complex and involves memory allocation.
errpipe_read, errpipe_write = os.pipe()
# errpipe_write must not be in the standard io 0, 1, or 2 fd range.
low_fds_to_close = []
while errpipe_write < 3:
low_fds_to_close.append(errpipe_write)
errpipe_write = os.dup(errpipe_write)
for low_fd in low_fds_to_close:
os.close(low_fd)
try:
try:
# We must avoid complex work that could involve
# malloc or free in the child process to avoid
# potential deadlocks, thus we do all this here.
# and pass it to fork_exec()

if env is not None:
env_list = []
for k, v in env.items():
k = os.fsencode(k)
if b'=' in k:
raise ValueError("illegal environment variable name")
env_list.append(k + b'=' + os.fsencode(v))
else:
env_list = None # Use execv instead of execve.
executable = os.fsencode(executable)
if os.path.dirname(executable):
executable_list = (executable,)
else:
# This matches the behavior of os._execvpe().
executable_list = tuple(
os.path.join(os.fsencode(dir), executable)
for dir in os.get_exec_path(env))
fds_to_keep = set(pass_fds)
fds_to_keep.add(errpipe_write)
> self.pid = _posixsubprocess.fork_exec(
args, executable_list,
close_fds, tuple(sorted(map(int, fds_to_keep))),
cwd, env_list,
p2cread, p2cwrite, c2pread, c2pwrite,
errread, errwrite,
errpipe_read, errpipe_write,
restore_signals, start_new_session,
gid, gids, uid, umask,
preexec_fn)
E BlockingIOError: [Errno 11] Resource temporarily unavailable

/usr/lib/python3.10/subprocess.py:1796: BlockingIOError

The above exception was the direct cause of the following exception:

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f5292d7f10>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
> output = SeleniumManager().binary_paths(self._to_args())

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:67:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:54: in binary_paths
return self._run(args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
completed_proc = subprocess.run(args, capture_output=True)
stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")
stderr = completed_proc.stderr.decode("utf-8").rstrip("\n")
output = json.loads(stdout) if stdout != "" else {"logs": [], "result": {}}
except Exception as err:
> raise WebDriverException(f"Unsuccessful command executed: {command}") from err
E selenium.common.exceptions.WebDriverException: Message: Unsuccessful command executed: /usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager --browser chrome --language-binding python --output json

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:121: WebDriverException

The above exception was the direct cause of the following exception:

browser_name = 'chrome', headless = True, locale_code = None
servername = 'localhost', proxy_string = None, proxy_auth = False
proxy_user = None, proxy_pass = None, proxy_bypass_list = None
proxy_pac_url = None, multi_proxy = False, user_agent = None
recorder_ext = False, disable_js = False, disable_csp = False, enable_ws = True
enable_sync = False, use_auto_ext = False, undetectable = False
uc_cdp_events = None, uc_subprocess = None, log_cdp_events = None
no_sandbox = False, disable_gpu = False, headless2 = False, incognito = False
guest_mode = False, dark_mode = False, devtools = False, remote_debug = False
enable_3d_apis = False, swiftshader = False, ad_block_on = False
host_resolver_rules = None, block_images = False, do_not_track = False
chromium_arg = None, firefox_arg = None, firefox_pref = None
user_data_dir = None, extension_zip = None, extension_dir = None
disable_features = None, binary_location = None, driver_version = None
page_load_strategy = None, use_wire = False, external_pdf = False
mobile_emulator = False, device_width = None, device_height = None
device_pixel_ratio = None

def get_local_driver(
browser_name,
headless,
locale_code,
servername,
proxy_string,
proxy_auth,
proxy_user,
proxy_pass,
proxy_bypass_list,
proxy_pac_url,
multi_proxy,
user_agent,
recorder_ext,
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
undetectable,
uc_cdp_events,
uc_subprocess,
log_cdp_events,
no_sandbox,
disable_gpu,
headless2,
incognito,
guest_mode,
dark_mode,
devtools,
remote_debug,
enable_3d_apis,
swiftshader,
ad_block_on,
host_resolver_rules,
block_images,
do_not_track,
chromium_arg,
firefox_arg,
firefox_pref,
user_data_dir,
extension_zip,
extension_dir,
disable_features,
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
):
"""Spins up a new web browser and returns the driver.
Can also be used to spin up additional browsers for the same test."""
downloads_path = DOWNLOADS_FOLDER
b_path = binary_location
if use_wire:
pip_find_lock = fasteners.InterProcessLock(
constants.PipInstall.FINDLOCK
)
with pip_find_lock: # Prevent issues with multiple processes
try:
from seleniumwire import webdriver
import blinker
try:
use_blinker_ver = constants.SeleniumWire.BLINKER_VER
if blinker.__version__ != use_blinker_ver:
shared_utils.pip_install(
"blinker", version=use_blinker_ver
)
except Exception:
pass
del blinker
except Exception:
shared_utils.pip_install(
"blinker", version=constants.SeleniumWire.BLINKER_VER
)
shared_utils.pip_install(
"selenium-wire", version=constants.SeleniumWire.VER
)
from seleniumwire import webdriver
warnings.simplefilter("ignore", category=DeprecationWarning)
else:
from selenium import webdriver

if browser_name == constants.Browser.FIREFOX:
firefox_options = _set_firefox_options(
downloads_path,
headless,
locale_code,
proxy_string,
proxy_bypass_list,
proxy_pac_url,
user_agent,
disable_js,
disable_csp,
firefox_arg,
firefox_pref,
)
if LOCAL_GECKODRIVER and os.path.exists(LOCAL_GECKODRIVER):
try:
make_driver_executable_if_not(LOCAL_GECKODRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make geckodriver"
" executable: %s" % e
)
elif not geckodriver_on_path():
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
log_d("\nWarning: geckodriver not found. Getting it now:")
try:
sb_install.main(override="geckodriver")
except Exception as e:
log_d("\nWarning: Could not install geckodriver: %s" % e)
sys.argv = sys_args # Put back the original sys args
else:
geckodriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with geckodriver_fixing_lock:
if not geckodriver_on_path():
sys_args = sys.argv # Save a copy of sys args
log_d(
"\nWarning: geckodriver not found. "
"Getting it now:"
)
sb_install.main(override="geckodriver")
sys.argv = sys_args # Put back original sys args
# Launch Firefox
if os.path.exists(LOCAL_GECKODRIVER):
service = FirefoxService(
executable_path=LOCAL_GECKODRIVER,
log_output=os.devnull,
)
try:
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
except BaseException as e:
if (
"geckodriver unexpectedly exited" in str(e)
or "Process unexpectedly closed" in str(e)
or "Failed to read marionette port" in str(e)
or "A connection attempt failed" in str(e)
or "Expected browser binary" in str(e)
or hasattr(e, "msg") and (
"geckodriver unexpectedly exited" in e.msg
or "Process unexpectedly closed" in e.msg
or "Failed to read marionette port" in e.msg
or "A connection attempt failed" in e.msg
or "Expected browser binary" in e.msg
)
):
time.sleep(0.1)
if (
IS_LINUX
and headless
and (
"unexpected" in str(e)
or (
hasattr(e, "msg") and "unexpected" in e.msg
)
)
):
firefox_options.add_argument("-headless")
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
else:
raise # Not an obvious fix.
else:
service = FirefoxService(log_output=os.devnull)
try:
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
except BaseException as e:
if (
"geckodriver unexpectedly exited" in str(e)
or "Process unexpectedly closed" in str(e)
or "Failed to read marionette port" in str(e)
or "A connection attempt failed" in str(e)
or "Expected browser binary" in str(e)
or hasattr(e, "msg") and (
"geckodriver unexpectedly exited" in e.msg
or "Process unexpectedly closed" in e.msg
or "Failed to read marionette port" in e.msg
or "A connection attempt failed" in e.msg
or "Expected browser binary" in e.msg
)
):
time.sleep(0.1)
if (
IS_LINUX
and headless
and (
"unexpected" in str(e)
or (
hasattr(e, "msg") and "unexpected" in e.msg
)
)
):
firefox_options.add_argument("-headless")
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
else:
raise # Not an obvious fix.
elif browser_name == constants.Browser.INTERNET_EXPLORER:
if not IS_WINDOWS:
raise Exception(
"IE Browser is for Windows-based systems only!"
)
from selenium.webdriver.ie.options import Options
from selenium.webdriver.ie.service import Service
ie_options = Options()
ie_options.add_argument("--guest")
ie_options.attach_to_edge_chrome = True
ie_options.ignore_protected_mode_settings = True
ie_options.ignore_zoom_level = True
ie_options.require_window_focus = False
ie_options.native_events = True
ie_options.full_page_screenshot = True
ie_options.persistent_hover = True
if LOCAL_IEDRIVER and os.path.exists(LOCAL_IEDRIVER):
try:
make_driver_executable_if_not(LOCAL_IEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make IEDriver executable: %s" % e
)
elif not iedriver_on_path():
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
log_d("\nWarning: IEDriver not found. Getting it now:")
sb_install.main(override="iedriver")
sys.argv = sys_args # Put back the original sys args
if LOCAL_HEADLESS_IEDRIVER and os.path.exists(LOCAL_HEADLESS_IEDRIVER):
try:
make_driver_executable_if_not(LOCAL_HEADLESS_IEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make HeadlessIEDriver executable: %s"
% e
)
elif not headless_iedriver_on_path():
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
log_d("\nWarning: HeadlessIEDriver not found. Getting it now:")
sb_install.main(override="iedriver")
sys.argv = sys_args # Put back the original sys args
d_b_c = "--disable-build-check"
logger = logging.getLogger("selenium")
logger.setLevel("INFO")
if not headless:
warnings.simplefilter("ignore", category=DeprecationWarning)
service = Service(service_args=[d_b_c], log_output=os.devnull)
driver = webdriver.Ie(service=service, options=ie_options)
return extend_driver(driver)
else:
warnings.simplefilter("ignore", category=DeprecationWarning)
service = Service(
executable_path=LOCAL_IEDRIVER,
service_args=[d_b_c],
log_output=os.devnull,
)
driver = webdriver.Ie(service=service, options=ie_options)
return extend_driver(driver)
elif browser_name == constants.Browser.EDGE:
prefs = {
"download.default_directory": downloads_path,
"download.directory_upgrade": True,
"download.prompt_for_download": False,
"credentials_enable_service": False,
"local_discovery.notifications_enabled": False,
"safebrowsing.disable_download_protection": True,
"safebrowsing.enabled": False, # Prevent PW "data breach" pop-ups
"omnibox-max-zero-suggest-matches": 0,
"omnibox-use-existing-autocomplete-client": 0,
"omnibox-trending-zero-prefix-suggestions-on-ntp": 0,
"omnibox-local-history-zero-suggest-beyond-ntp": 0,
"omnibox-on-focus-suggestions-contextual-web": 0,
"omnibox-on-focus-suggestions-srp": 0,
"omnibox-zero-suggest-prefetching": 0,
"omnibox-zero-suggest-prefetching-on-srp": 0,
"omnibox-zero-suggest-prefetching-on-web": 0,
"omnibox-zero-suggest-in-memory-caching": 0,
"content_settings.exceptions.automatic_downloads.*.setting": 1,
"default_content_setting_values.notifications": 0,
"default_content_settings.popups": 0,
"managed_default_content_settings.popups": 0,
"profile.password_manager_enabled": False,
"profile.default_content_setting_values.notifications": 2,
"profile.default_content_settings.popups": 0,
"profile.managed_default_content_settings.popups": 0,
"profile.default_content_setting_values.automatic_downloads": 1,
}
use_version = "latest"
major_edge_version = None
saved_mev = None
use_br_version_for_edge = False
use_exact_version_for_edge = False
try:
if binary_location:
try:
major_edge_version = (
detect_b_ver.get_browser_version_from_binary(
binary_location
)
)
saved_mev = major_edge_version
major_edge_version = saved_mev.split(".")[0]
if len(major_edge_version) < 2:
major_edge_version = None
except Exception:
major_edge_version = None
if not major_edge_version:
br_app = "edge"
major_edge_version = (
detect_b_ver.get_browser_version_from_os(br_app)
)
saved_mev = major_edge_version
major_edge_version = major_edge_version.split(".")[0]
if int(major_edge_version) < 80:
major_edge_version = None
elif int(major_edge_version) >= 115:
if (
driver_version == "browser"
and saved_mev
and len(saved_mev.split(".")) == 4
):
driver_version = saved_mev
use_br_version_for_edge = True
except Exception:
major_edge_version = None
if driver_version and "." in driver_version:
use_exact_version_for_edge = True
if use_br_version_for_edge:
major_edge_version = saved_mev
if major_edge_version:
use_version = major_edge_version
edge_driver_version = None
edgedriver_upgrade_needed = False
if os.path.exists(LOCAL_EDGEDRIVER):
try:
output = subprocess.check_output(
'"%s" --version' % LOCAL_EDGEDRIVER, shell=True
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
if output.split(" ")[0] == "MSEdgeDriver":
# MSEdgeDriver VERSION
output = output.split(" ")[1]
if use_exact_version_for_edge:
edge_driver_version = output.split(" ")[0]
output = output.split(".")[0]
elif output.split(" ")[0] == "Microsoft":
output = output.split(" ")[3]
if use_exact_version_for_edge:
edge_driver_version = output.split(" ")[0]
output = output.split(".")[0]
else:
output = 0
if int(output) >= 2:
if not use_exact_version_for_edge:
edge_driver_version = output
if driver_version == "keep":
driver_version = edge_driver_version
except Exception:
pass
use_version = find_edgedriver_version_to_use(
use_version, driver_version
)
local_edgedriver_exists = False
if LOCAL_EDGEDRIVER and os.path.exists(LOCAL_EDGEDRIVER):
local_edgedriver_exists = True
if (
use_version != "latest"
and edge_driver_version
and use_version != edge_driver_version
):
edgedriver_upgrade_needed = True
else:
try:
make_driver_executable_if_not(LOCAL_EDGEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make edgedriver"
" executable: %s" % e
)
if not local_edgedriver_exists or edgedriver_upgrade_needed:
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
msg = "Microsoft Edge Driver not found."
if edgedriver_upgrade_needed:
msg = "Microsoft Edge Driver update needed."
sys_args = sys.argv # Save a copy of current sys args
log_d("\n%s Getting it now:" % msg)
sb_install.main(override="edgedriver %s" % use_version)
sys.argv = sys_args # Put back the original sys args
else:
edgedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with edgedriver_fixing_lock:
msg = "Microsoft Edge Driver not found."
if edgedriver_upgrade_needed:
msg = "Microsoft Edge Driver update needed."
sys_args = sys.argv # Save a copy of current sys args
log_d("\n%s Getting it now:" % msg)
sb_install.main(override="edgedriver %s" % use_version)
sys.argv = sys_args # Put back the original sys args

# For Microsoft Edge (Chromium) version 80 or higher
Edge = webdriver.edge.webdriver.WebDriver
EdgeOptions = webdriver.edge.webdriver.Options
if LOCAL_EDGEDRIVER and os.path.exists(LOCAL_EDGEDRIVER):
try:
make_driver_executable_if_not(LOCAL_EDGEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make edgedriver"
" executable: %s" % e
)
edge_options = EdgeOptions()
edge_options.use_chromium = True
if locale_code:
prefs["intl.accept_languages"] = locale_code
if block_images:
prefs["profile.managed_default_content_settings.images"] = 2
if disable_js:
prefs["profile.managed_default_content_settings.javascript"] = 2
if do_not_track:
prefs["enable_do_not_track"] = True
if external_pdf:
prefs["plugins.always_open_pdf_externally"] = True
pdce = "user_experience_metrics.personalization_data_consent_enabled"
prefs[pdce] = True # Remove "Personalize your web experience" prompt
edge_options.add_experimental_option("prefs", prefs)
edge_options.add_argument(
"--disable-blink-features=AutomationControlled"
)
edge_options.add_experimental_option(
"excludeSwitches", ["enable-automation", "enable-logging"]
)
if log_cdp_events:
edge_options.set_capability(
"ms:loggingPrefs", {"performance": "ALL", "browser": "ALL"}
)
if host_resolver_rules:
edge_options.add_argument(
"--host-resolver-rules=%s" % host_resolver_rules
)
if not enable_sync:
edge_options.add_argument("--disable-sync")
if (
not recorder_ext and not disable_csp and not proxy_auth
):
edge_options.add_argument("--guest")
if dark_mode:
edge_options.add_argument("--enable-features=WebContentsForceDark")
if headless2:
try:
if use_version == "latest" or int(use_version) >= 109:
edge_options.add_argument("--headless=new")
else:
edge_options.add_argument("--headless=chrome")
except Exception:
edge_options.add_argument("--headless=new")
elif headless and undetectable:
# (For later: UC Mode doesn't support Edge now)
try:
if int(use_version) >= 109:
edge_options.add_argument("--headless=new")
elif (
int(use_version) >= 96
and int(use_version) <= 108
):
edge_options.add_argument("--headless=chrome")
else:
pass # Will need Xvfb on Linux
except Exception:
pass
elif headless:
if "--headless" not in edge_options.arguments:
edge_options.add_argument("--headless")
if mobile_emulator and not is_using_uc(undetectable, browser_name):
emulator_settings = {}
device_metrics = {}
if (
isinstance(device_width, int)
and isinstance(device_height, int)
and isinstance(device_pixel_ratio, (int, float))
):
device_metrics["width"] = device_width
device_metrics["height"] = device_height
device_metrics["pixelRatio"] = device_pixel_ratio
else:
device_metrics["width"] = constants.Mobile.WIDTH
device_metrics["height"] = constants.Mobile.HEIGHT
device_metrics["pixelRatio"] = constants.Mobile.RATIO
emulator_settings["deviceMetrics"] = device_metrics
if user_agent:
emulator_settings["userAgent"] = user_agent
edge_options.add_experimental_option(
"mobileEmulation", emulator_settings
)
if headless or headless2:
edge_options.add_argument(
"--window-size=%s,%s" % (
settings.HEADLESS_START_WIDTH,
settings.HEADLESS_START_HEIGHT,
)
)
else:
edge_options.add_argument(
"--window-size=%s,%s" % (
settings.CHROME_START_WIDTH,
settings.CHROME_START_HEIGHT,
)
)
if user_data_dir and not is_using_uc(undetectable, browser_name):
abs_path = os.path.abspath(user_data_dir)
edge_options.add_argument("--user-data-dir=%s" % abs_path)
if extension_zip:
# Can be a comma-separated list of .ZIP or .CRX files
extension_zip_list = extension_zip.split(",")
for extension_zip_item in extension_zip_list:
abs_path = os.path.abspath(extension_zip_item)
edge_options.add_extension(abs_path)
if extension_dir:
# load-extension input can be a comma-separated list
abs_path = os.path.abspath(extension_dir)
edge_options = add_chrome_ext_dir(edge_options, abs_path)
edge_options.add_argument("--disable-infobars")
edge_options.add_argument("--disable-notifications")
edge_options.add_argument("--disable-save-password-bubble")
edge_options.add_argument("--disable-single-click-autofill")
edge_options.add_argument(
"--disable-autofill-keyboard-accessory-view[8]"
)
edge_options.add_argument("--safebrowsing-disable-download-protection")
edge_options.add_argument("--disable-search-engine-choice-screen")
edge_options.add_argument("--disable-browser-side-navigation")
edge_options.add_argument("--disable-translate")
if not enable_ws:
edge_options.add_argument("--disable-web-security")
edge_options.add_argument("--homepage=about:blank")
edge_options.add_argument("--dns-prefetch-disable")
edge_options.add_argument("--dom-automation")
edge_options.add_argument("--disable-hang-monitor")
edge_options.add_argument("--disable-prompt-on-repost")
if not enable_3d_apis:
edge_options.add_argument("--disable-3d-apis")
if headless or headless2 or is_using_uc(undetectable, browser_name):
edge_options.add_argument("--disable-renderer-backgrounding")
edge_options.add_argument("--disable-backgrounding-occluded-windows")
edge_options.add_argument("--disable-client-side-phishing-detection")
edge_options.add_argument("--disable-oopr-debug-crash-dump")
edge_options.add_argument("--disable-top-sites")
edge_options.add_argument("--ash-no-nudges")
edge_options.add_argument("--no-crash-upload")
edge_options.add_argument("--deny-permission-prompts")
if (
page_load_strategy
and page_load_strategy.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
edge_options.page_load_strategy = page_load_strategy.lower()
elif (
not page_load_strategy
and hasattr(settings, "PAGE_LOAD_STRATEGY")
and settings.PAGE_LOAD_STRATEGY
and settings.PAGE_LOAD_STRATEGY.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
edge_options.page_load_strategy = (
settings.PAGE_LOAD_STRATEGY.lower()
)
if (settings.DISABLE_CSP_ON_CHROME or disable_csp) and not headless:
# Headless Edge doesn't support extensions, which are required
# for disabling the Content Security Policy on Edge
edge_options = _add_chrome_disable_csp_extension(edge_options)
if ad_block_on and not headless:
edge_options = _add_chrome_ad_block_extension(edge_options)
if recorder_ext and not headless:
edge_options = _add_chrome_recorder_extension(edge_options)
if proxy_string:
if proxy_auth:
edge_options = _add_chrome_proxy_extension(
edge_options,
proxy_string,
proxy_user,
proxy_pass,
proxy_bypass_list,
zip_it=True,
multi_proxy=multi_proxy,
)
edge_options.add_argument("--proxy-server=%s" % proxy_string)
if proxy_bypass_list:
edge_options.add_argument(
"--proxy-bypass-list=%s" % proxy_bypass_list
)
elif proxy_pac_url:
if proxy_auth:
edge_options = _add_chrome_proxy_extension(
edge_options,
None,
proxy_user,
proxy_pass,
proxy_bypass_list,
zip_it=True,
multi_proxy=multi_proxy,
)
edge_options.add_argument("--proxy-pac-url=%s" % proxy_pac_url)
edge_options.add_argument("--test-type")
edge_options.add_argument("--log-level=3")
edge_options.add_argument("--no-first-run")
edge_options.add_argument("--ignore-certificate-errors")
if devtools and not headless:
edge_options.add_argument("--auto-open-devtools-for-tabs")
edge_options.add_argument("--allow-file-access-from-files")
edge_options.add_argument("--allow-insecure-localhost")
edge_options.add_argument("--allow-running-insecure-content")
if user_agent:
edge_options.add_argument("--user-agent=%s" % user_agent)
if (
IS_LINUX
or (IS_MAC and not is_using_uc(undetectable, browser_name))
):
edge_options.add_argument("--no-sandbox")
if remote_debug:
# To access the Debugger, go to: edge://inspect/#devices
# while a Chromium driver is running.
# Info: https://chromedevtools.github.io/devtools-protocol/
args = " ".join(sys.argv)
free_port = 9222
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
free_port = service_utils.free_port()
edge_options.add_argument("--remote-debugging-port=%s" % free_port)
if swiftshader:
edge_options.add_argument("--use-gl=angle")
edge_options.add_argument("--use-angle=swiftshader-webgl")
elif (
not is_using_uc(undetectable, browser_name)
and not enable_3d_apis
):
edge_options.add_argument("--disable-gpu")
if IS_LINUX:
edge_options.add_argument("--disable-dev-shm-usage")
extra_disabled_features = []
set_binary = False
if chromium_arg:
# Can be a comma-separated list of Chromium args
chromium_arg_list = chromium_arg.split(",")
for chromium_arg_item in chromium_arg_list:
chromium_arg_item = chromium_arg_item.strip()
if not chromium_arg_item.startswith("--"):
if chromium_arg_item.startswith("-"):
chromium_arg_item = "-" + chromium_arg_item
else:
chromium_arg_item = "--" + chromium_arg_item
if "set-binary" in chromium_arg_item:
set_binary = True
elif "disable-features=" in chromium_arg_item:
d_f = chromium_arg_item.split("disable-features=")[-1]
extra_disabled_features.append(d_f)
elif len(chromium_arg_item) >= 3:
edge_options.add_argument(chromium_arg_item)
if disable_features:
extra_disabled_features.extend(disable_features.split(","))
edge_options.add_argument(
'--simulate-outdated-no-au="Tue, 31 Dec 2099 23:59:59 GMT"'
)
edge_options.add_argument("--disable-ipc-flooding-protection")
edge_options.add_argument("--disable-password-generation")
edge_options.add_argument("--disable-domain-reliability")
edge_options.add_argument("--disable-component-update")
edge_options.add_argument("--disable-breakpad")
included_disabled_features = []
included_disabled_features.append("OptimizationHints")
included_disabled_features.append("OptimizationHintsFetching")
included_disabled_features.append("Translate")
included_disabled_features.append("OptimizationTargetPrediction")
included_disabled_features.append("OptimizationGuideModelDownloading")
included_disabled_features.append("InsecureDownloadWarnings")
included_disabled_features.append("InterestFeedContentSuggestions")
included_disabled_features.append("PrivacySandboxSettings4")
included_disabled_features.append("SidePanelPinning")
included_disabled_features.append("UserAgentClientHint")
for item in extra_disabled_features:
if item not in included_disabled_features:
included_disabled_features.append(item)
d_f_string = ",".join(included_disabled_features)
edge_options.add_argument("--disable-features=%s" % d_f_string)
if (set_binary or IS_LINUX) and not binary_location:
br_app = "edge"
binary_loc = detect_b_ver.get_binary_location(br_app)
if os.path.exists(binary_loc):
binary_location = binary_loc
if binary_location:
edge_options.binary_location = binary_location
service = EdgeService(
executable_path=LOCAL_EDGEDRIVER,
log_output=os.devnull,
service_args=["--disable-build-check"],
)
try:
driver = Edge(service=service, options=edge_options)
except Exception as e:
if not hasattr(e, "msg"):
raise
auto_upgrade_edgedriver = False
edge_version = None
if (
"This version of MSEdgeDriver only supports" in e.msg
or "This version of Microsoft Edge WebDriver" in e.msg
):
if "Current browser version is " in e.msg:
auto_upgrade_edgedriver = True
edge_version = e.msg.split(
"Current browser version is "
)[1].split(" ")[0]
elif "only supports MSEdge version " in e.msg:
auto_upgrade_edgedriver = True
edge_version = e.msg.split(
"only supports MSEdge version "
)[1].split(" ")[0]
elif "DevToolsActivePort file doesn't exist" in e.msg:
# https://stackoverflow.com/a/56638103/7058266
args = " ".join(sys.argv)
free_port = 9222
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
free_port = service_utils.free_port()
edge_options.add_argument(
"--remote-debugging-port=%s" % free_port
)
driver = Edge(service=service, options=edge_options)
return extend_driver(driver)
if not auto_upgrade_edgedriver:
raise # Not an obvious fix.
else:
pass # Try upgrading EdgeDriver to match Edge.
args = " ".join(sys.argv)
if "-n" in sys.argv or " -n=" in args or args == "-c":
edgedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with edgedriver_fixing_lock:
try:
if not _was_driver_repaired():
_repair_edgedriver(edge_version)
_mark_driver_repaired()
except Exception:
pass
else:
try:
if not _was_driver_repaired():
_repair_edgedriver(edge_version)
_mark_driver_repaired()
except Exception:
pass
driver = Edge(service=service, options=edge_options)
return extend_driver(driver)
elif browser_name == constants.Browser.SAFARI:
args = " ".join(sys.argv)
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
# Skip if multithreaded
raise Exception("Can't run Safari tests in multithreaded mode!")
warnings.simplefilter("ignore", category=DeprecationWarning)
from selenium.webdriver.safari.options import Options as SafariOptions
service = SafariService(quiet=False)
options = SafariOptions()
if (
page_load_strategy
and page_load_strategy.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
options.page_load_strategy = page_load_strategy.lower()
elif (
not page_load_strategy
and hasattr(settings, "PAGE_LOAD_STRATEGY")
and settings.PAGE_LOAD_STRATEGY
and settings.PAGE_LOAD_STRATEGY.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
options.page_load_strategy = settings.PAGE_LOAD_STRATEGY.lower()
driver = webdriver.safari.webdriver.WebDriver(
service=service, options=options
)
return extend_driver(driver)
elif browser_name == constants.Browser.GOOGLE_CHROME:
try:
chrome_options = _set_chrome_options(
browser_name,
downloads_path,
headless,
locale_code,
proxy_string,
proxy_auth,
proxy_user,
proxy_pass,
proxy_bypass_list,
proxy_pac_url,
multi_proxy,
user_agent,
recorder_ext,
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
undetectable,
uc_cdp_events,
uc_subprocess,
log_cdp_events,
no_sandbox,
disable_gpu,
headless2,
incognito,
guest_mode,
dark_mode,
devtools,
remote_debug,
enable_3d_apis,
swiftshader,
ad_block_on,
host_resolver_rules,
block_images,
do_not_track,
chromium_arg,
user_data_dir,
extension_zip,
extension_dir,
disable_features,
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
servername,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
use_version = "latest"
major_chrome_version = None
saved_mcv = None
full_ch_version = None
full_ch_driver_version = None
use_br_version_for_uc = False
try:
if chrome_options.binary_location:
try:
major_chrome_version = (
detect_b_ver.get_browser_version_from_binary(
chrome_options.binary_location,
)
)
saved_mcv = major_chrome_version
major_chrome_version = saved_mcv.split(".")[0]
if len(major_chrome_version) < 2:
major_chrome_version = None
except Exception:
major_chrome_version = None
if not major_chrome_version:
br_app = "google-chrome"
full_ch_version = (
detect_b_ver.get_browser_version_from_os(br_app)
)
saved_mcv = full_ch_version
major_chrome_version = full_ch_version.split(".")[0]
if int(major_chrome_version) < 67:
major_chrome_version = None
elif (
int(major_chrome_version) >= 67
and int(major_chrome_version) <= 72
):
# chromedrivers 2.41 - 2.46 could be swapped with 72
major_chrome_version = "72"
elif int(major_chrome_version) >= 115:
if (
driver_version == "browser"
and saved_mcv
and len(saved_mcv.split(".")) == 4
):
driver_version = saved_mcv
if is_using_uc(undetectable, browser_name):
use_br_version_for_uc = True
if (
(headless or headless2)
and IS_WINDOWS
and major_chrome_version
and int(major_chrome_version) >= 117
and not is_using_uc(undetectable, browser_name)
and not (remote_debug or devtools or use_wire)
and not (proxy_string or multi_proxy or proxy_pac_url)
and (not chromium_arg or "debug" not in chromium_arg)
and (not servername or servername == "localhost")
):
# Hide the "DevTools listening on ..." message.
# https://bugs.chromium.org
# /p/chromedriver/issues/detail?id=4403#c35
# (Only when the remote debugging port is not needed.)
chrome_options.add_argument("--remote-debugging-pipe")
except Exception:
major_chrome_version = None
if major_chrome_version:
use_version = major_chrome_version
ch_driver_version = None
path_chromedriver = chromedriver_on_path()
if os.path.exists(LOCAL_CHROMEDRIVER):
try:
output = subprocess.check_output(
'"%s" --version' % LOCAL_CHROMEDRIVER, shell=True
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
full_ch_driver_version = output.split(" ")[1]
output = full_ch_driver_version.split(".")[0]
if int(output) >= 2:
ch_driver_version = output
if driver_version == "keep":
driver_version = ch_driver_version
except Exception:
pass
elif path_chromedriver:
try:
make_driver_executable_if_not(path_chromedriver)
except Exception as e:
logging.debug(
"\nWarning: Could not make chromedriver"
" executable: %s" % e
)
try:
output = subprocess.check_output(
'"%s" --version' % path_chromedriver, shell=True
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
full_ch_driver_version = output.split(" ")[1]
output = full_ch_driver_version.split(".")[0]
if int(output) >= 2:
ch_driver_version = output
if driver_version == "keep":
use_version = ch_driver_version
except Exception:
pass
disable_build_check = True
uc_driver_version = None
if is_using_uc(undetectable, browser_name):
if use_br_version_for_uc or driver_version == "mlatest":
uc_driver_version = get_uc_driver_version(full=True)
full_ch_driver_version = uc_driver_version
else:
uc_driver_version = get_uc_driver_version()
if multi_proxy:
sb_config.multi_proxy = True
if uc_driver_version and driver_version == "keep":
driver_version = uc_driver_version
use_version = find_chromedriver_version_to_use(
use_version, driver_version
)
if headless2:
try:
if (
use_version == "latest"
or int(str(use_version).split(".")[0]) >= 109
):
chrome_options.add_argument("--headless=new")
else:
chrome_options.add_argument("--headless=chrome")
except Exception:
chrome_options.add_argument("--headless=new")
elif headless and undetectable:
try:
int_use_version = int(str(use_version).split(".")[0])
if int_use_version >= 109:
chrome_options.add_argument("--headless=new")
elif (
int_use_version >= 96
and int_use_version <= 108
):
chrome_options.add_argument("--headless=chrome")
else:
pass # Will need Xvfb on Linux
except Exception:
pass # Will need Xvfb on Linux
elif headless:
if "--headless" not in chrome_options.arguments:
chrome_options.add_argument("--headless")
if LOCAL_CHROMEDRIVER and os.path.exists(LOCAL_CHROMEDRIVER):
try:
make_driver_executable_if_not(LOCAL_CHROMEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make chromedriver"
" executable: %s" % e
)
use_uc = is_using_uc(undetectable, browser_name)
make_uc_driver_from_chromedriver = False
local_ch_exists = (
LOCAL_CHROMEDRIVER and os.path.exists(LOCAL_CHROMEDRIVER)
)
"""If no LOCAL_CHROMEDRIVER, but path_chromedriver, and the
browser version nearly matches the driver version, then use
the path_chromedriver instead of downloading a new driver.
Eg. 116.0.* for both is close, but not 116.0.* and 116.1.*"""
browser_driver_close_match = False
if (
path_chromedriver
and full_ch_version
and full_ch_driver_version
):
full_ch_v_p = full_ch_version.split(".")[0:2]
full_ch_driver_v_p = full_ch_driver_version.split(".")[0:2]
if (
full_ch_v_p == full_ch_driver_v_p
or driver_version == "keep"
):
browser_driver_close_match = True
# If not ARM MAC and need to use uc_driver (and it's missing),
# and already have chromedriver with the correct version,
# then copy chromedriver to uc_driver (and it'll get patched).
if (
not IS_ARM_MAC
and use_uc
and (
(
(local_ch_exists or path_chromedriver)
and use_version == ch_driver_version
and (
not os.path.exists(LOCAL_UC_DRIVER)
or uc_driver_version != use_version
)
)
or (
local_ch_exists
and use_version == "latest"
and not os.path.exists(LOCAL_UC_DRIVER)
)
)
):
make_uc_driver_from_chromedriver = True
elif (
(use_uc and not os.path.exists(LOCAL_UC_DRIVER))
or (not use_uc and not path_chromedriver)
or (
not use_uc
and use_version != "latest" # Browser version detected
and (ch_driver_version or not local_ch_exists)
and (
use_version.split(".")[0] != ch_driver_version
or (
not local_ch_exists
and use_version.isnumeric()
and int(use_version) >= 115
and not browser_driver_close_match
)
)
)
or (
use_uc
and use_version != "latest" # Browser version detected
and uc_driver_version != use_version
)
or (
full_ch_driver_version # Also used for the uc_driver
and driver_version
and len(str(driver_version).split(".")) == 4
and full_ch_driver_version != driver_version
)
):
# chromedriver download needed in the seleniumbase/drivers dir
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
msg = "chromedriver update needed. Getting it now:"
if not path_chromedriver:
msg = "chromedriver not found. Getting it now:"
if use_uc and not os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver not found. Getting it now:"
if use_uc and os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver update needed. Getting it now:"
log_d("\nWarning: %s" % msg)
force_uc = False
intel_for_uc = False
if use_uc:
force_uc = True
if IS_ARM_MAC and use_uc:
intel_for_uc = True # Use Intel's driver for UC Mode
try:
sb_install.main(
override="chromedriver %s" % use_version,
intel_for_uc=intel_for_uc,
force_uc=force_uc,
)
except Exception:
d_latest = get_latest_chromedriver_version()
if (
d_latest
and use_version != "latest"
and int(use_version) > int(d_latest.split(".")[0])
):
disable_build_check = True
d_latest_major = d_latest.split(".")[0]
if (
not path_chromedriver
or (
ch_driver_version
and (
int(ch_driver_version)
< int(d_latest_major)
)
)
):
sb_install.main(override="chromedriver latest")
sys.argv = sys_args # Put back the original sys args
else:
# (Multithreaded)
chromedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with chromedriver_fixing_lock:
msg = "chromedriver update needed. Getting it now:"
if not path_chromedriver:
msg = "chromedriver not found. Getting it now:"
if use_uc and not os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver not found. Getting it now:"
if use_uc and os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver update needed. Getting it now:"
force_uc = False
intel_for_uc = False
if use_uc:
force_uc = True
if IS_ARM_MAC and use_uc:
intel_for_uc = True # Use Intel driver for UC Mode
if os.path.exists(LOCAL_CHROMEDRIVER):
try:
output = subprocess.check_output(
'"%s" --version' % LOCAL_CHROMEDRIVER,
shell=True,
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
full_ch_driver_version = output.split(" ")[1]
output = full_ch_driver_version.split(".")[0]
if int(output) >= 2:
ch_driver_version = output
except Exception:
pass
if (
(
not use_uc
and not os.path.exists(LOCAL_CHROMEDRIVER)
)
or (use_uc and not os.path.exists(LOCAL_UC_DRIVER))
or (
not use_uc
and (
use_version.split(".")[0]
!= ch_driver_version
)
)
or (
use_uc
and (
use_version.split(".")[0]
!= get_uc_driver_version()
)
)
):
log_d("\nWarning: %s" % msg)
sys_args = sys.argv # Save a copy of sys args
try:
sb_install.main(
override="chromedriver %s" % use_version,
intel_for_uc=intel_for_uc,
force_uc=force_uc,
)
except Exception:
d_latest = get_latest_chromedriver_version()
if (
d_latest
and use_version != "latest"
and (
int(use_version)
> int(d_latest.split(".")[0])
)
):
disable_build_check = True
d_latest_major = d_latest.split(".")[0]
if (
not path_chromedriver
or (
ch_driver_version
and (
int(ch_driver_version)
< int(d_latest_major)
)
)
):
sb_install.main(
override="chromedriver latest"
)
finally:
sys.argv = sys_args # Put back original args
service_args = []
if disable_build_check:
service_args = ["--disable-build-check"]
if is_using_uc(undetectable, browser_name):
uc_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with uc_lock: # Avoid multithreaded issues
if make_uc_driver_from_chromedriver:
if os.path.exists(LOCAL_CHROMEDRIVER):
shutil.copyfile(
LOCAL_CHROMEDRIVER, LOCAL_UC_DRIVER
)
elif os.path.exists(path_chromedriver):
shutil.copyfile(
path_chromedriver, LOCAL_UC_DRIVER
)
try:
make_driver_executable_if_not(LOCAL_UC_DRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make uc_driver"
" executable: %s" % e
)
if (
not headless
or not IS_LINUX
or is_using_uc(undetectable, browser_name)
):
uc_activated = False
try:
if (
os.path.exists(LOCAL_CHROMEDRIVER)
or is_using_uc(undetectable, browser_name)
):
if headless and not IS_LINUX:
undetectable = False # No support for headless
if is_using_uc(undetectable, browser_name):
from seleniumbase import undetected
from urllib.error import URLError
if IS_LINUX:
if "--headless" in (
chrome_options.arguments
):
chrome_options.arguments.remove(
"--headless"
)
uc_chrome_version = None
if (
use_version.isnumeric()
and int(use_version) >= 72
):
uc_chrome_version = int(use_version)
elif (
str(use_version).split(".")[0].isnumeric()
and int(str(use_version).split(".")[0]) >= 72
):
uc_chrome_version = (
int(str(use_version).split(".")[0])
)
cdp_events = uc_cdp_events
cert = "unable to get local issuer certificate"
mac_certificate_error = False
if (
use_version.isnumeric()
and int(use_version) <= 74
):
chrome_options.add_experimental_option(
"w3c", True
)
if (
(not user_agent or "Headless" in user_agent)
and uc_chrome_version
and uc_chrome_version >= 117
and (headless or headless2)
and hasattr(sb_config, "uc_agent_cache")
):
user_agent = sb_config.uc_agent_cache
chrome_options.add_argument(
"--user-agent=%s" % user_agent
)
try:
if (
(
not user_agent
or "Headless" in user_agent
)
and uc_chrome_version
and uc_chrome_version >= 117
and (headless or headless2)
):
from seleniumbase.console_scripts import (
sb_install
)
sb_config.uc_user_agent_cache = True
headless_options = _set_chrome_options(
browser_name,
downloads_path,
True, # headless
locale_code,
None, # proxy_string
None, # proxy_auth
None, # proxy_user
None, # proxy_pass
None, # proxy_bypass_list
None, # proxy_pac_url
None, # multi_proxy
None, # user_agent
None, # recorder_ext
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
False, # undetectable
False, # uc_cdp_events
False, # uc_subprocess
False, # log_cdp_events
no_sandbox,
disable_gpu,
False, # headless2
incognito,
guest_mode,
dark_mode,
None, # devtools
remote_debug,
enable_3d_apis,
swiftshader,
None, # ad_block_on
None, # host_resolver_rules
block_images,
do_not_track,
None, # chromium_arg
None, # user_data_dir
None, # extension_zip
None, # extension_dir
None, # disable_features
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
servername,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
if (
not path_chromedriver
or (
ch_driver_version
and use_version
and (
int(ch_driver_version)
< int(str(
use_version).split(".")[0]
)
)
)
):
sb_install.main(
override="chromedriver %s"
% use_version,
intel_for_uc=False,
force_uc=False,
)
d_b_c = "--disable-build-check"
if os.path.exists(LOCAL_CHROMEDRIVER):
service = ChromeService(
executable_path=LOCAL_CHROMEDRIVER,
log_output=os.devnull,
service_args=[d_b_c],
)
driver = webdriver.Chrome(
service=service,
options=headless_options,
)
else:
service = ChromeService(
log_output=os.devnull,
service_args=[d_b_c],
)
driver = webdriver.Chrome(
service=service,
options=headless_options,
)
try:
user_agent = driver.execute_script(
"return navigator.userAgent;"
)
if (
major_chrome_version
and full_ch_version
and full_ch_version.count(".") == 3
and full_ch_version in user_agent
):
mcv = major_chrome_version
user_agent = user_agent.replace(
"Chrome/%s" % full_ch_version,
"Chrome/%s.0.0.0" % mcv
)
user_agent = user_agent.replace(
"Headless", ""
)
chrome_options.add_argument(
"--user-agent=%s" % user_agent
)
sb_config.uc_agent_cache = user_agent
except Exception:
pass
driver.quit()
except Exception:
pass
uc_path = None
if os.path.exists(LOCAL_UC_DRIVER):
uc_path = LOCAL_UC_DRIVER
uc_path = os.path.realpath(uc_path)
try:
driver = undetected.Chrome(
options=chrome_options,
user_data_dir=user_data_dir,
driver_executable_path=uc_path,
browser_executable_path=b_path,
enable_cdp_events=cdp_events,
headless=False, # Xvfb needed!
version_main=uc_chrome_version,
use_subprocess=True, # Always!
)
uc_activated = True
except URLError as e:
if cert in e.args[0] and IS_MAC:
mac_certificate_error = True
else:
raise
except SessionNotCreatedException:
time.sleep(0.2)
driver = undetected.Chrome(
options=chrome_options,
user_data_dir=user_data_dir,
driver_executable_path=uc_path,
browser_executable_path=b_path,
enable_cdp_events=cdp_events,
headless=False, # Xvfb needed!
version_main=uc_chrome_version,
use_subprocess=True, # Always!
)
uc_activated = True
if mac_certificate_error:
cf_lock_path = (
constants.MultiBrowser.CERT_FIXING_LOCK
)
cf_lock = fasteners.InterProcessLock(
constants.MultiBrowser.CERT_FIXING_LOCK
)
if not os.path.exists(cf_lock_path):
# Avoid multithreaded issues
with cf_lock:
# Install Python Certificates (MAC)
os.system(
r"bash /Applications/Python*/"
r"Install\ "
r"Certificates.command"
)
driver = undetected.Chrome(
options=chrome_options,
user_data_dir=user_data_dir,
driver_executable_path=uc_path,
browser_executable_path=b_path,
enable_cdp_events=cdp_events,
headless=False, # Xvfb needed!
version_main=uc_chrome_version,
use_subprocess=True, # Always!
)
uc_activated = True
else:
if (
use_version.isnumeric()
and int(use_version) <= 74
):
chrome_options.add_experimental_option(
"w3c", True
)
service = ChromeService(
executable_path=LOCAL_CHROMEDRIVER,
log_output=os.devnull,
service_args=service_args,
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
else:
service = ChromeService(
log_output=os.devnull,
service_args=service_args,
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
except Exception as e:
if not hasattr(e, "msg"):
raise
auto_upgrade_chromedriver = False
if "This version of ChromeDriver only supports" in e.msg:
auto_upgrade_chromedriver = True
elif "Chrome version must be between" in e.msg:
auto_upgrade_chromedriver = True
elif "Missing or invalid capabilities" in e.msg:
chrome_options.add_experimental_option("w3c", True)
service = ChromeService(
log_output=os.devnull,
service_args=service_args,
)
with warnings.catch_warnings():
warnings.simplefilter(
"ignore", category=DeprecationWarning
)
driver = webdriver.Chrome(
service=service, options=chrome_options
)
return extend_driver(driver)
if not auto_upgrade_chromedriver:
raise # Not an obvious fix.
else:
pass # Try upgrading ChromeDriver to match Chrome.
mcv = None # Major Chrome Version
if "Current browser version is " in e.msg:
line = e.msg.split("Current browser version is ")[1]
browser_version = line.split(" ")[0]
major_chrome_version = browser_version.split(".")[0]
if (
major_chrome_version.isnumeric()
and int(major_chrome_version) >= 86
):
mcv = major_chrome_version
mcv = find_chromedriver_version_to_use(
mcv, driver_version
)
headless_options = _set_chrome_options(
browser_name,
downloads_path,
True, # headless
locale_code,
None, # proxy_string
None, # proxy_auth
None, # proxy_user
None, # proxy_pass
None, # proxy_bypass_list
None, # proxy_pac_url
None, # multi_proxy
None, # user_agent
None, # recorder_ext
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
False, # undetectable
False, # uc_cdp_events
False, # uc_subprocess
False, # log_cdp_events
no_sandbox,
disable_gpu,
False, # headless2
incognito,
guest_mode,
dark_mode,
None, # devtools
remote_debug,
enable_3d_apis,
swiftshader,
None, # ad_block_on
None, # host_resolver_rules
block_images,
do_not_track,
None, # chromium_arg
None, # user_data_dir
None, # extension_zip
None, # extension_dir
None, # disable_features
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
servername,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
args = " ".join(sys.argv)
if "-n" in sys.argv or " -n=" in args or args == "-c":
chromedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with chromedriver_fixing_lock:
if not _was_driver_repaired():
_repair_chromedriver(
chrome_options, headless_options, mcv
)
_mark_driver_repaired()
else:
if not _was_driver_repaired():
_repair_chromedriver(
chrome_options, headless_options, mcv
)
_mark_driver_repaired()
if os.path.exists(LOCAL_CHROMEDRIVER):
service = ChromeService(
executable_path=LOCAL_CHROMEDRIVER,
log_output=os.devnull,
service_args=["--disable-build-check"],
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
else:
service = ChromeService(
log_output=os.devnull,
service_args=["--disable-build-check"],
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
driver.default_get = driver.get # Save copy of original
if uc_activated:
driver.get = lambda url: uc_special_open_if_cf(
driver,
url,
proxy_string,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
driver.uc_open = lambda url: uc_open(driver, url)
driver.uc_open_with_tab = (
lambda url: uc_open_with_tab(driver, url)
)
driver.uc_open_with_reconnect = (
lambda *args, **kwargs: uc_open_with_reconnect(
driver, *args, **kwargs
)
)
driver.uc_open_with_disconnect = (
lambda *args, **kwargs: uc_open_with_disconnect(
driver, *args, **kwargs
)
)
driver.uc_click = lambda *args, **kwargs: uc_click(
driver, *args, **kwargs
)
driver.uc_gui_press_key = (
lambda *args, **kwargs: uc_gui_press_key(
driver, *args, **kwargs
)
)
driver.uc_gui_press_keys = (
lambda *args, **kwargs: uc_gui_press_keys(
driver, *args, **kwargs
)
)
driver.uc_gui_write = (
lambda *args, **kwargs: uc_gui_write(
driver, *args, **kwargs
)
)
driver.uc_gui_click_x_y = (
lambda *args, **kwargs: uc_gui_click_x_y(
driver, *args, **kwargs
)
)
driver.uc_gui_click_captcha = (
lambda *args, **kwargs: uc_gui_click_captcha(
driver, *args, **kwargs
)
)
driver.uc_gui_click_cf = (
lambda *args, **kwargs: uc_gui_click_cf(
driver, *args, **kwargs
)
)
driver.uc_gui_click_rc = (
lambda *args, **kwargs: uc_gui_click_rc(
driver, *args, **kwargs
)
)
driver.uc_gui_handle_captcha = (
lambda *args, **kwargs: uc_gui_handle_captcha(
driver, *args, **kwargs
)
)
driver.uc_gui_handle_cf = (
lambda *args, **kwargs: uc_gui_handle_cf(
driver, *args, **kwargs
)
)
driver.uc_gui_handle_rc = (
lambda *args, **kwargs: uc_gui_handle_rc(
driver, *args, **kwargs
)
)
driver.uc_switch_to_frame = (
lambda *args, **kwargs: uc_switch_to_frame(
driver, *args, **kwargs
)
)
driver._is_hidden = (headless or headless2)
driver._is_using_uc = True
if mobile_emulator:
uc_metrics = {}
if (
isinstance(device_width, int)
and isinstance(device_height, int)
and isinstance(device_pixel_ratio, (int, float))
):
uc_metrics["width"] = device_width
uc_metrics["height"] = device_height
uc_metrics["pixelRatio"] = device_pixel_ratio
else:
uc_metrics["width"] = constants.Mobile.WIDTH
uc_metrics["height"] = constants.Mobile.HEIGHT
uc_metrics["pixelRatio"] = constants.Mobile.RATIO
set_device_metrics_override = dict(
{
"width": uc_metrics["width"],
"height": uc_metrics["height"],
"deviceScaleFactor": uc_metrics["pixelRatio"],
"mobile": True
}
)
try:
driver.execute_cdp_cmd(
'Emulation.setDeviceMetricsOverride',
set_device_metrics_override
)
except Exception:
pass
return extend_driver(driver)
else: # Running headless on Linux (and not using --uc)
try:
> driver = webdriver.Chrome(options=chrome_options)

/usr/local/lib/python3.10/dist-packages/seleniumbase/core/browser_launcher.py:4613:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chrome/webdriver.py:45: in __init__
super().__init__(
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chromium/webdriver.py:50: in __init__
if finder.get_browser_path():
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:47: in get_browser_path
return self._binary_paths()["browser_path"]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f5292d7f10>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
output = SeleniumManager().binary_paths(self._to_args())
if Path(output["driver_path"]).is_file():
self._paths["driver_path"] = output["driver_path"]
else:
raise ValueError(f'The driver path is not a valid file: {output["driver_path"]}')
if Path(output["browser_path"]).is_file():
self._paths["browser_path"] = output["browser_path"]
else:
raise ValueError(f'The browser path is not a valid file: {output["browser_path"]}')
except Exception as err:
msg = f"Unable to obtain driver for {browser}"
> raise NoSuchDriverException(msg) from err
E selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for chrome; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:78: NoSuchDriverException

During handling of the above exception, another exception occurred:

args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
> completed_proc = subprocess.run(args, capture_output=True)

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:116:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.10/subprocess.py:503: in run
with Popen(*popenargs, **kwargs) as process:
/usr/lib/python3.10/subprocess.py:971: in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <Popen: returncode: None args: ['/usr/local/lib/python3.10/dist-packages/sel...>
args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]
executable = b'/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager'
preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None
startupinfo = None, creationflags = 0, shell = False, p2cread = -1
p2cwrite = -1, c2pread = 15, c2pwrite = 18, errread = 19, errwrite = 20
restore_signals = True, gid = None, gids = None, uid = None, umask = -1
start_new_session = False

def _execute_child(self, args, executable, preexec_fn, close_fds,
pass_fds, cwd, env,
startupinfo, creationflags, shell,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite,
restore_signals,
gid, gids, uid, umask,
start_new_session):
"""Execute program (POSIX version)"""

if isinstance(args, (str, bytes)):
args = [args]
elif isinstance(args, os.PathLike):
if shell:
raise TypeError('path-like args is not allowed when '
'shell is true')
args = [args]
else:
args = list(args)

if shell:
# On Android the default shell is at '/system/bin/sh'.
unix_shell = ('/system/bin/sh' if
hasattr(sys, 'getandroidapilevel') else '/bin/sh')
args = [unix_shell, "-c"] + args
if executable:
args[0] = executable

if executable is None:
executable = args[0]

sys.audit("subprocess.Popen", executable, args, cwd, env)

if (_USE_POSIX_SPAWN
and os.path.dirname(executable)
and preexec_fn is None
and not close_fds
and not pass_fds
and cwd is None
and (p2cread == -1 or p2cread > 2)
and (c2pwrite == -1 or c2pwrite > 2)
and (errwrite == -1 or errwrite > 2)
and not start_new_session
and gid is None
and gids is None
and uid is None
and umask < 0):
self._posix_spawn(args, executable, env, restore_signals,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite)
return

orig_executable = executable

# For transferring possible exec failure from child to parent.
# Data format: "exception name:hex errno:description"
# Pickle is not used; it is complex and involves memory allocation.
errpipe_read, errpipe_write = os.pipe()
# errpipe_write must not be in the standard io 0, 1, or 2 fd range.
low_fds_to_close = []
while errpipe_write < 3:
low_fds_to_close.append(errpipe_write)
errpipe_write = os.dup(errpipe_write)
for low_fd in low_fds_to_close:
os.close(low_fd)
try:
try:
# We must avoid complex work that could involve
# malloc or free in the child process to avoid
# potential deadlocks, thus we do all this here.
# and pass it to fork_exec()

if env is not None:
env_list = []
for k, v in env.items():
k = os.fsencode(k)
if b'=' in k:
raise ValueError("illegal environment variable name")
env_list.append(k + b'=' + os.fsencode(v))
else:
env_list = None # Use execv instead of execve.
executable = os.fsencode(executable)
if os.path.dirname(executable):
executable_list = (executable,)
else:
# This matches the behavior of os._execvpe().
executable_list = tuple(
os.path.join(os.fsencode(dir), executable)
for dir in os.get_exec_path(env))
fds_to_keep = set(pass_fds)
fds_to_keep.add(errpipe_write)
> self.pid = _posixsubprocess.fork_exec(
args, executable_list,
close_fds, tuple(sorted(map(int, fds_to_keep))),
cwd, env_list,
p2cread, p2cwrite, c2pread, c2pwrite,
errread, errwrite,
errpipe_read, errpipe_write,
restore_signals, start_new_session,
gid, gids, uid, umask,
preexec_fn)
E BlockingIOError: [Errno 11] Resource temporarily unavailable

/usr/lib/python3.10/subprocess.py:1796: BlockingIOError

The above exception was the direct cause of the following exception:

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f529314070>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
> output = SeleniumManager().binary_paths(self._to_args())

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:67:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:54: in binary_paths
return self._run(args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
completed_proc = subprocess.run(args, capture_output=True)
stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")
stderr = completed_proc.stderr.decode("utf-8").rstrip("\n")
output = json.loads(stdout) if stdout != "" else {"logs": [], "result": {}}
except Exception as err:
> raise WebDriverException(f"Unsuccessful command executed: {command}") from err
E selenium.common.exceptions.WebDriverException: Message: Unsuccessful command executed: /usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager --browser chrome --language-binding python --output json

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:121: WebDriverException

The above exception was the direct cause of the following exception:
/usr/local/lib/python3.10/dist-packages/seleniumbase/fixtures/base_case.py:14917: in setUp
self.driver = self.get_new_driver(
/usr/local/lib/python3.10/dist-packages/seleniumbase/fixtures/base_case.py:4101: in get_new_driver
new_driver = browser_launcher.get_driver(
/usr/local/lib/python3.10/dist-packages/seleniumbase/core/browser_launcher.py:2339: in get_driver
return get_local_driver(
/usr/local/lib/python3.10/dist-packages/seleniumbase/core/browser_launcher.py:4695: in get_local_driver
driver = webdriver.Chrome(
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chrome/webdriver.py:45: in __init__
super().__init__(
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chromium/webdriver.py:50: in __init__
if finder.get_browser_path():
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:47: in get_browser_path
return self._binary_paths()["browser_path"]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f529314070>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
output = SeleniumManager().binary_paths(self._to_args())
if Path(output["driver_path"]).is_file():
self._paths["driver_path"] = output["driver_path"]
else:
raise ValueError(f'The driver path is not a valid file: {output["driver_path"]}')
if Path(output["browser_path"]).is_file():
self._paths["browser_path"] = output["browser_path"]
else:
raise ValueError(f'The browser path is not a valid file: {output["browser_path"]}')
except Exception as err:
msg = f"Unable to obtain driver for {browser}"
> raise NoSuchDriverException(msg) from err
E selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for chrome; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:78: NoSuchDriverException
Failed FOrUS_testing.py::FOrusWebsite::test_all_subdomains_existieren_und_aktuell 0.16
args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
> completed_proc = subprocess.run(args, capture_output=True)

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:116:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.10/subprocess.py:503: in run
with Popen(*popenargs, **kwargs) as process:
/usr/lib/python3.10/subprocess.py:971: in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <Popen: returncode: None args: ['/usr/local/lib/python3.10/dist-packages/sel...>
args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]
executable = b'/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager'
preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None
startupinfo = None, creationflags = 0, shell = False, p2cread = -1
p2cwrite = -1, c2pread = 15, c2pwrite = 18, errread = 19, errwrite = 20
restore_signals = True, gid = None, gids = None, uid = None, umask = -1
start_new_session = False

def _execute_child(self, args, executable, preexec_fn, close_fds,
pass_fds, cwd, env,
startupinfo, creationflags, shell,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite,
restore_signals,
gid, gids, uid, umask,
start_new_session):
"""Execute program (POSIX version)"""

if isinstance(args, (str, bytes)):
args = [args]
elif isinstance(args, os.PathLike):
if shell:
raise TypeError('path-like args is not allowed when '
'shell is true')
args = [args]
else:
args = list(args)

if shell:
# On Android the default shell is at '/system/bin/sh'.
unix_shell = ('/system/bin/sh' if
hasattr(sys, 'getandroidapilevel') else '/bin/sh')
args = [unix_shell, "-c"] + args
if executable:
args[0] = executable

if executable is None:
executable = args[0]

sys.audit("subprocess.Popen", executable, args, cwd, env)

if (_USE_POSIX_SPAWN
and os.path.dirname(executable)
and preexec_fn is None
and not close_fds
and not pass_fds
and cwd is None
and (p2cread == -1 or p2cread > 2)
and (c2pwrite == -1 or c2pwrite > 2)
and (errwrite == -1 or errwrite > 2)
and not start_new_session
and gid is None
and gids is None
and uid is None
and umask < 0):
self._posix_spawn(args, executable, env, restore_signals,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite)
return

orig_executable = executable

# For transferring possible exec failure from child to parent.
# Data format: "exception name:hex errno:description"
# Pickle is not used; it is complex and involves memory allocation.
errpipe_read, errpipe_write = os.pipe()
# errpipe_write must not be in the standard io 0, 1, or 2 fd range.
low_fds_to_close = []
while errpipe_write < 3:
low_fds_to_close.append(errpipe_write)
errpipe_write = os.dup(errpipe_write)
for low_fd in low_fds_to_close:
os.close(low_fd)
try:
try:
# We must avoid complex work that could involve
# malloc or free in the child process to avoid
# potential deadlocks, thus we do all this here.
# and pass it to fork_exec()

if env is not None:
env_list = []
for k, v in env.items():
k = os.fsencode(k)
if b'=' in k:
raise ValueError("illegal environment variable name")
env_list.append(k + b'=' + os.fsencode(v))
else:
env_list = None # Use execv instead of execve.
executable = os.fsencode(executable)
if os.path.dirname(executable):
executable_list = (executable,)
else:
# This matches the behavior of os._execvpe().
executable_list = tuple(
os.path.join(os.fsencode(dir), executable)
for dir in os.get_exec_path(env))
fds_to_keep = set(pass_fds)
fds_to_keep.add(errpipe_write)
> self.pid = _posixsubprocess.fork_exec(
args, executable_list,
close_fds, tuple(sorted(map(int, fds_to_keep))),
cwd, env_list,
p2cread, p2cwrite, c2pread, c2pwrite,
errread, errwrite,
errpipe_read, errpipe_write,
restore_signals, start_new_session,
gid, gids, uid, umask,
preexec_fn)
E BlockingIOError: [Errno 11] Resource temporarily unavailable

/usr/lib/python3.10/subprocess.py:1796: BlockingIOError

The above exception was the direct cause of the following exception:

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f5289abdc0>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
> output = SeleniumManager().binary_paths(self._to_args())

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:67:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:54: in binary_paths
return self._run(args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
completed_proc = subprocess.run(args, capture_output=True)
stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")
stderr = completed_proc.stderr.decode("utf-8").rstrip("\n")
output = json.loads(stdout) if stdout != "" else {"logs": [], "result": {}}
except Exception as err:
> raise WebDriverException(f"Unsuccessful command executed: {command}") from err
E selenium.common.exceptions.WebDriverException: Message: Unsuccessful command executed: /usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager --browser chrome --language-binding python --output json

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:121: WebDriverException

The above exception was the direct cause of the following exception:

browser_name = 'chrome', headless = True, locale_code = None
servername = 'localhost', proxy_string = None, proxy_auth = False
proxy_user = None, proxy_pass = None, proxy_bypass_list = None
proxy_pac_url = None, multi_proxy = False, user_agent = None
recorder_ext = False, disable_js = False, disable_csp = False, enable_ws = True
enable_sync = False, use_auto_ext = False, undetectable = False
uc_cdp_events = None, uc_subprocess = None, log_cdp_events = None
no_sandbox = False, disable_gpu = False, headless2 = False, incognito = False
guest_mode = False, dark_mode = False, devtools = False, remote_debug = False
enable_3d_apis = False, swiftshader = False, ad_block_on = False
host_resolver_rules = None, block_images = False, do_not_track = False
chromium_arg = None, firefox_arg = None, firefox_pref = None
user_data_dir = None, extension_zip = None, extension_dir = None
disable_features = None, binary_location = None, driver_version = None
page_load_strategy = None, use_wire = False, external_pdf = False
mobile_emulator = False, device_width = None, device_height = None
device_pixel_ratio = None

def get_local_driver(
browser_name,
headless,
locale_code,
servername,
proxy_string,
proxy_auth,
proxy_user,
proxy_pass,
proxy_bypass_list,
proxy_pac_url,
multi_proxy,
user_agent,
recorder_ext,
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
undetectable,
uc_cdp_events,
uc_subprocess,
log_cdp_events,
no_sandbox,
disable_gpu,
headless2,
incognito,
guest_mode,
dark_mode,
devtools,
remote_debug,
enable_3d_apis,
swiftshader,
ad_block_on,
host_resolver_rules,
block_images,
do_not_track,
chromium_arg,
firefox_arg,
firefox_pref,
user_data_dir,
extension_zip,
extension_dir,
disable_features,
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
):
"""Spins up a new web browser and returns the driver.
Can also be used to spin up additional browsers for the same test."""
downloads_path = DOWNLOADS_FOLDER
b_path = binary_location
if use_wire:
pip_find_lock = fasteners.InterProcessLock(
constants.PipInstall.FINDLOCK
)
with pip_find_lock: # Prevent issues with multiple processes
try:
from seleniumwire import webdriver
import blinker
try:
use_blinker_ver = constants.SeleniumWire.BLINKER_VER
if blinker.__version__ != use_blinker_ver:
shared_utils.pip_install(
"blinker", version=use_blinker_ver
)
except Exception:
pass
del blinker
except Exception:
shared_utils.pip_install(
"blinker", version=constants.SeleniumWire.BLINKER_VER
)
shared_utils.pip_install(
"selenium-wire", version=constants.SeleniumWire.VER
)
from seleniumwire import webdriver
warnings.simplefilter("ignore", category=DeprecationWarning)
else:
from selenium import webdriver

if browser_name == constants.Browser.FIREFOX:
firefox_options = _set_firefox_options(
downloads_path,
headless,
locale_code,
proxy_string,
proxy_bypass_list,
proxy_pac_url,
user_agent,
disable_js,
disable_csp,
firefox_arg,
firefox_pref,
)
if LOCAL_GECKODRIVER and os.path.exists(LOCAL_GECKODRIVER):
try:
make_driver_executable_if_not(LOCAL_GECKODRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make geckodriver"
" executable: %s" % e
)
elif not geckodriver_on_path():
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
log_d("\nWarning: geckodriver not found. Getting it now:")
try:
sb_install.main(override="geckodriver")
except Exception as e:
log_d("\nWarning: Could not install geckodriver: %s" % e)
sys.argv = sys_args # Put back the original sys args
else:
geckodriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with geckodriver_fixing_lock:
if not geckodriver_on_path():
sys_args = sys.argv # Save a copy of sys args
log_d(
"\nWarning: geckodriver not found. "
"Getting it now:"
)
sb_install.main(override="geckodriver")
sys.argv = sys_args # Put back original sys args
# Launch Firefox
if os.path.exists(LOCAL_GECKODRIVER):
service = FirefoxService(
executable_path=LOCAL_GECKODRIVER,
log_output=os.devnull,
)
try:
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
except BaseException as e:
if (
"geckodriver unexpectedly exited" in str(e)
or "Process unexpectedly closed" in str(e)
or "Failed to read marionette port" in str(e)
or "A connection attempt failed" in str(e)
or "Expected browser binary" in str(e)
or hasattr(e, "msg") and (
"geckodriver unexpectedly exited" in e.msg
or "Process unexpectedly closed" in e.msg
or "Failed to read marionette port" in e.msg
or "A connection attempt failed" in e.msg
or "Expected browser binary" in e.msg
)
):
time.sleep(0.1)
if (
IS_LINUX
and headless
and (
"unexpected" in str(e)
or (
hasattr(e, "msg") and "unexpected" in e.msg
)
)
):
firefox_options.add_argument("-headless")
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
else:
raise # Not an obvious fix.
else:
service = FirefoxService(log_output=os.devnull)
try:
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
except BaseException as e:
if (
"geckodriver unexpectedly exited" in str(e)
or "Process unexpectedly closed" in str(e)
or "Failed to read marionette port" in str(e)
or "A connection attempt failed" in str(e)
or "Expected browser binary" in str(e)
or hasattr(e, "msg") and (
"geckodriver unexpectedly exited" in e.msg
or "Process unexpectedly closed" in e.msg
or "Failed to read marionette port" in e.msg
or "A connection attempt failed" in e.msg
or "Expected browser binary" in e.msg
)
):
time.sleep(0.1)
if (
IS_LINUX
and headless
and (
"unexpected" in str(e)
or (
hasattr(e, "msg") and "unexpected" in e.msg
)
)
):
firefox_options.add_argument("-headless")
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
else:
raise # Not an obvious fix.
elif browser_name == constants.Browser.INTERNET_EXPLORER:
if not IS_WINDOWS:
raise Exception(
"IE Browser is for Windows-based systems only!"
)
from selenium.webdriver.ie.options import Options
from selenium.webdriver.ie.service import Service
ie_options = Options()
ie_options.add_argument("--guest")
ie_options.attach_to_edge_chrome = True
ie_options.ignore_protected_mode_settings = True
ie_options.ignore_zoom_level = True
ie_options.require_window_focus = False
ie_options.native_events = True
ie_options.full_page_screenshot = True
ie_options.persistent_hover = True
if LOCAL_IEDRIVER and os.path.exists(LOCAL_IEDRIVER):
try:
make_driver_executable_if_not(LOCAL_IEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make IEDriver executable: %s" % e
)
elif not iedriver_on_path():
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
log_d("\nWarning: IEDriver not found. Getting it now:")
sb_install.main(override="iedriver")
sys.argv = sys_args # Put back the original sys args
if LOCAL_HEADLESS_IEDRIVER and os.path.exists(LOCAL_HEADLESS_IEDRIVER):
try:
make_driver_executable_if_not(LOCAL_HEADLESS_IEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make HeadlessIEDriver executable: %s"
% e
)
elif not headless_iedriver_on_path():
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
log_d("\nWarning: HeadlessIEDriver not found. Getting it now:")
sb_install.main(override="iedriver")
sys.argv = sys_args # Put back the original sys args
d_b_c = "--disable-build-check"
logger = logging.getLogger("selenium")
logger.setLevel("INFO")
if not headless:
warnings.simplefilter("ignore", category=DeprecationWarning)
service = Service(service_args=[d_b_c], log_output=os.devnull)
driver = webdriver.Ie(service=service, options=ie_options)
return extend_driver(driver)
else:
warnings.simplefilter("ignore", category=DeprecationWarning)
service = Service(
executable_path=LOCAL_IEDRIVER,
service_args=[d_b_c],
log_output=os.devnull,
)
driver = webdriver.Ie(service=service, options=ie_options)
return extend_driver(driver)
elif browser_name == constants.Browser.EDGE:
prefs = {
"download.default_directory": downloads_path,
"download.directory_upgrade": True,
"download.prompt_for_download": False,
"credentials_enable_service": False,
"local_discovery.notifications_enabled": False,
"safebrowsing.disable_download_protection": True,
"safebrowsing.enabled": False, # Prevent PW "data breach" pop-ups
"omnibox-max-zero-suggest-matches": 0,
"omnibox-use-existing-autocomplete-client": 0,
"omnibox-trending-zero-prefix-suggestions-on-ntp": 0,
"omnibox-local-history-zero-suggest-beyond-ntp": 0,
"omnibox-on-focus-suggestions-contextual-web": 0,
"omnibox-on-focus-suggestions-srp": 0,
"omnibox-zero-suggest-prefetching": 0,
"omnibox-zero-suggest-prefetching-on-srp": 0,
"omnibox-zero-suggest-prefetching-on-web": 0,
"omnibox-zero-suggest-in-memory-caching": 0,
"content_settings.exceptions.automatic_downloads.*.setting": 1,
"default_content_setting_values.notifications": 0,
"default_content_settings.popups": 0,
"managed_default_content_settings.popups": 0,
"profile.password_manager_enabled": False,
"profile.default_content_setting_values.notifications": 2,
"profile.default_content_settings.popups": 0,
"profile.managed_default_content_settings.popups": 0,
"profile.default_content_setting_values.automatic_downloads": 1,
}
use_version = "latest"
major_edge_version = None
saved_mev = None
use_br_version_for_edge = False
use_exact_version_for_edge = False
try:
if binary_location:
try:
major_edge_version = (
detect_b_ver.get_browser_version_from_binary(
binary_location
)
)
saved_mev = major_edge_version
major_edge_version = saved_mev.split(".")[0]
if len(major_edge_version) < 2:
major_edge_version = None
except Exception:
major_edge_version = None
if not major_edge_version:
br_app = "edge"
major_edge_version = (
detect_b_ver.get_browser_version_from_os(br_app)
)
saved_mev = major_edge_version
major_edge_version = major_edge_version.split(".")[0]
if int(major_edge_version) < 80:
major_edge_version = None
elif int(major_edge_version) >= 115:
if (
driver_version == "browser"
and saved_mev
and len(saved_mev.split(".")) == 4
):
driver_version = saved_mev
use_br_version_for_edge = True
except Exception:
major_edge_version = None
if driver_version and "." in driver_version:
use_exact_version_for_edge = True
if use_br_version_for_edge:
major_edge_version = saved_mev
if major_edge_version:
use_version = major_edge_version
edge_driver_version = None
edgedriver_upgrade_needed = False
if os.path.exists(LOCAL_EDGEDRIVER):
try:
output = subprocess.check_output(
'"%s" --version' % LOCAL_EDGEDRIVER, shell=True
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
if output.split(" ")[0] == "MSEdgeDriver":
# MSEdgeDriver VERSION
output = output.split(" ")[1]
if use_exact_version_for_edge:
edge_driver_version = output.split(" ")[0]
output = output.split(".")[0]
elif output.split(" ")[0] == "Microsoft":
output = output.split(" ")[3]
if use_exact_version_for_edge:
edge_driver_version = output.split(" ")[0]
output = output.split(".")[0]
else:
output = 0
if int(output) >= 2:
if not use_exact_version_for_edge:
edge_driver_version = output
if driver_version == "keep":
driver_version = edge_driver_version
except Exception:
pass
use_version = find_edgedriver_version_to_use(
use_version, driver_version
)
local_edgedriver_exists = False
if LOCAL_EDGEDRIVER and os.path.exists(LOCAL_EDGEDRIVER):
local_edgedriver_exists = True
if (
use_version != "latest"
and edge_driver_version
and use_version != edge_driver_version
):
edgedriver_upgrade_needed = True
else:
try:
make_driver_executable_if_not(LOCAL_EDGEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make edgedriver"
" executable: %s" % e
)
if not local_edgedriver_exists or edgedriver_upgrade_needed:
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
msg = "Microsoft Edge Driver not found."
if edgedriver_upgrade_needed:
msg = "Microsoft Edge Driver update needed."
sys_args = sys.argv # Save a copy of current sys args
log_d("\n%s Getting it now:" % msg)
sb_install.main(override="edgedriver %s" % use_version)
sys.argv = sys_args # Put back the original sys args
else:
edgedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with edgedriver_fixing_lock:
msg = "Microsoft Edge Driver not found."
if edgedriver_upgrade_needed:
msg = "Microsoft Edge Driver update needed."
sys_args = sys.argv # Save a copy of current sys args
log_d("\n%s Getting it now:" % msg)
sb_install.main(override="edgedriver %s" % use_version)
sys.argv = sys_args # Put back the original sys args

# For Microsoft Edge (Chromium) version 80 or higher
Edge = webdriver.edge.webdriver.WebDriver
EdgeOptions = webdriver.edge.webdriver.Options
if LOCAL_EDGEDRIVER and os.path.exists(LOCAL_EDGEDRIVER):
try:
make_driver_executable_if_not(LOCAL_EDGEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make edgedriver"
" executable: %s" % e
)
edge_options = EdgeOptions()
edge_options.use_chromium = True
if locale_code:
prefs["intl.accept_languages"] = locale_code
if block_images:
prefs["profile.managed_default_content_settings.images"] = 2
if disable_js:
prefs["profile.managed_default_content_settings.javascript"] = 2
if do_not_track:
prefs["enable_do_not_track"] = True
if external_pdf:
prefs["plugins.always_open_pdf_externally"] = True
pdce = "user_experience_metrics.personalization_data_consent_enabled"
prefs[pdce] = True # Remove "Personalize your web experience" prompt
edge_options.add_experimental_option("prefs", prefs)
edge_options.add_argument(
"--disable-blink-features=AutomationControlled"
)
edge_options.add_experimental_option(
"excludeSwitches", ["enable-automation", "enable-logging"]
)
if log_cdp_events:
edge_options.set_capability(
"ms:loggingPrefs", {"performance": "ALL", "browser": "ALL"}
)
if host_resolver_rules:
edge_options.add_argument(
"--host-resolver-rules=%s" % host_resolver_rules
)
if not enable_sync:
edge_options.add_argument("--disable-sync")
if (
not recorder_ext and not disable_csp and not proxy_auth
):
edge_options.add_argument("--guest")
if dark_mode:
edge_options.add_argument("--enable-features=WebContentsForceDark")
if headless2:
try:
if use_version == "latest" or int(use_version) >= 109:
edge_options.add_argument("--headless=new")
else:
edge_options.add_argument("--headless=chrome")
except Exception:
edge_options.add_argument("--headless=new")
elif headless and undetectable:
# (For later: UC Mode doesn't support Edge now)
try:
if int(use_version) >= 109:
edge_options.add_argument("--headless=new")
elif (
int(use_version) >= 96
and int(use_version) <= 108
):
edge_options.add_argument("--headless=chrome")
else:
pass # Will need Xvfb on Linux
except Exception:
pass
elif headless:
if "--headless" not in edge_options.arguments:
edge_options.add_argument("--headless")
if mobile_emulator and not is_using_uc(undetectable, browser_name):
emulator_settings = {}
device_metrics = {}
if (
isinstance(device_width, int)
and isinstance(device_height, int)
and isinstance(device_pixel_ratio, (int, float))
):
device_metrics["width"] = device_width
device_metrics["height"] = device_height
device_metrics["pixelRatio"] = device_pixel_ratio
else:
device_metrics["width"] = constants.Mobile.WIDTH
device_metrics["height"] = constants.Mobile.HEIGHT
device_metrics["pixelRatio"] = constants.Mobile.RATIO
emulator_settings["deviceMetrics"] = device_metrics
if user_agent:
emulator_settings["userAgent"] = user_agent
edge_options.add_experimental_option(
"mobileEmulation", emulator_settings
)
if headless or headless2:
edge_options.add_argument(
"--window-size=%s,%s" % (
settings.HEADLESS_START_WIDTH,
settings.HEADLESS_START_HEIGHT,
)
)
else:
edge_options.add_argument(
"--window-size=%s,%s" % (
settings.CHROME_START_WIDTH,
settings.CHROME_START_HEIGHT,
)
)
if user_data_dir and not is_using_uc(undetectable, browser_name):
abs_path = os.path.abspath(user_data_dir)
edge_options.add_argument("--user-data-dir=%s" % abs_path)
if extension_zip:
# Can be a comma-separated list of .ZIP or .CRX files
extension_zip_list = extension_zip.split(",")
for extension_zip_item in extension_zip_list:
abs_path = os.path.abspath(extension_zip_item)
edge_options.add_extension(abs_path)
if extension_dir:
# load-extension input can be a comma-separated list
abs_path = os.path.abspath(extension_dir)
edge_options = add_chrome_ext_dir(edge_options, abs_path)
edge_options.add_argument("--disable-infobars")
edge_options.add_argument("--disable-notifications")
edge_options.add_argument("--disable-save-password-bubble")
edge_options.add_argument("--disable-single-click-autofill")
edge_options.add_argument(
"--disable-autofill-keyboard-accessory-view[8]"
)
edge_options.add_argument("--safebrowsing-disable-download-protection")
edge_options.add_argument("--disable-search-engine-choice-screen")
edge_options.add_argument("--disable-browser-side-navigation")
edge_options.add_argument("--disable-translate")
if not enable_ws:
edge_options.add_argument("--disable-web-security")
edge_options.add_argument("--homepage=about:blank")
edge_options.add_argument("--dns-prefetch-disable")
edge_options.add_argument("--dom-automation")
edge_options.add_argument("--disable-hang-monitor")
edge_options.add_argument("--disable-prompt-on-repost")
if not enable_3d_apis:
edge_options.add_argument("--disable-3d-apis")
if headless or headless2 or is_using_uc(undetectable, browser_name):
edge_options.add_argument("--disable-renderer-backgrounding")
edge_options.add_argument("--disable-backgrounding-occluded-windows")
edge_options.add_argument("--disable-client-side-phishing-detection")
edge_options.add_argument("--disable-oopr-debug-crash-dump")
edge_options.add_argument("--disable-top-sites")
edge_options.add_argument("--ash-no-nudges")
edge_options.add_argument("--no-crash-upload")
edge_options.add_argument("--deny-permission-prompts")
if (
page_load_strategy
and page_load_strategy.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
edge_options.page_load_strategy = page_load_strategy.lower()
elif (
not page_load_strategy
and hasattr(settings, "PAGE_LOAD_STRATEGY")
and settings.PAGE_LOAD_STRATEGY
and settings.PAGE_LOAD_STRATEGY.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
edge_options.page_load_strategy = (
settings.PAGE_LOAD_STRATEGY.lower()
)
if (settings.DISABLE_CSP_ON_CHROME or disable_csp) and not headless:
# Headless Edge doesn't support extensions, which are required
# for disabling the Content Security Policy on Edge
edge_options = _add_chrome_disable_csp_extension(edge_options)
if ad_block_on and not headless:
edge_options = _add_chrome_ad_block_extension(edge_options)
if recorder_ext and not headless:
edge_options = _add_chrome_recorder_extension(edge_options)
if proxy_string:
if proxy_auth:
edge_options = _add_chrome_proxy_extension(
edge_options,
proxy_string,
proxy_user,
proxy_pass,
proxy_bypass_list,
zip_it=True,
multi_proxy=multi_proxy,
)
edge_options.add_argument("--proxy-server=%s" % proxy_string)
if proxy_bypass_list:
edge_options.add_argument(
"--proxy-bypass-list=%s" % proxy_bypass_list
)
elif proxy_pac_url:
if proxy_auth:
edge_options = _add_chrome_proxy_extension(
edge_options,
None,
proxy_user,
proxy_pass,
proxy_bypass_list,
zip_it=True,
multi_proxy=multi_proxy,
)
edge_options.add_argument("--proxy-pac-url=%s" % proxy_pac_url)
edge_options.add_argument("--test-type")
edge_options.add_argument("--log-level=3")
edge_options.add_argument("--no-first-run")
edge_options.add_argument("--ignore-certificate-errors")
if devtools and not headless:
edge_options.add_argument("--auto-open-devtools-for-tabs")
edge_options.add_argument("--allow-file-access-from-files")
edge_options.add_argument("--allow-insecure-localhost")
edge_options.add_argument("--allow-running-insecure-content")
if user_agent:
edge_options.add_argument("--user-agent=%s" % user_agent)
if (
IS_LINUX
or (IS_MAC and not is_using_uc(undetectable, browser_name))
):
edge_options.add_argument("--no-sandbox")
if remote_debug:
# To access the Debugger, go to: edge://inspect/#devices
# while a Chromium driver is running.
# Info: https://chromedevtools.github.io/devtools-protocol/
args = " ".join(sys.argv)
free_port = 9222
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
free_port = service_utils.free_port()
edge_options.add_argument("--remote-debugging-port=%s" % free_port)
if swiftshader:
edge_options.add_argument("--use-gl=angle")
edge_options.add_argument("--use-angle=swiftshader-webgl")
elif (
not is_using_uc(undetectable, browser_name)
and not enable_3d_apis
):
edge_options.add_argument("--disable-gpu")
if IS_LINUX:
edge_options.add_argument("--disable-dev-shm-usage")
extra_disabled_features = []
set_binary = False
if chromium_arg:
# Can be a comma-separated list of Chromium args
chromium_arg_list = chromium_arg.split(",")
for chromium_arg_item in chromium_arg_list:
chromium_arg_item = chromium_arg_item.strip()
if not chromium_arg_item.startswith("--"):
if chromium_arg_item.startswith("-"):
chromium_arg_item = "-" + chromium_arg_item
else:
chromium_arg_item = "--" + chromium_arg_item
if "set-binary" in chromium_arg_item:
set_binary = True
elif "disable-features=" in chromium_arg_item:
d_f = chromium_arg_item.split("disable-features=")[-1]
extra_disabled_features.append(d_f)
elif len(chromium_arg_item) >= 3:
edge_options.add_argument(chromium_arg_item)
if disable_features:
extra_disabled_features.extend(disable_features.split(","))
edge_options.add_argument(
'--simulate-outdated-no-au="Tue, 31 Dec 2099 23:59:59 GMT"'
)
edge_options.add_argument("--disable-ipc-flooding-protection")
edge_options.add_argument("--disable-password-generation")
edge_options.add_argument("--disable-domain-reliability")
edge_options.add_argument("--disable-component-update")
edge_options.add_argument("--disable-breakpad")
included_disabled_features = []
included_disabled_features.append("OptimizationHints")
included_disabled_features.append("OptimizationHintsFetching")
included_disabled_features.append("Translate")
included_disabled_features.append("OptimizationTargetPrediction")
included_disabled_features.append("OptimizationGuideModelDownloading")
included_disabled_features.append("InsecureDownloadWarnings")
included_disabled_features.append("InterestFeedContentSuggestions")
included_disabled_features.append("PrivacySandboxSettings4")
included_disabled_features.append("SidePanelPinning")
included_disabled_features.append("UserAgentClientHint")
for item in extra_disabled_features:
if item not in included_disabled_features:
included_disabled_features.append(item)
d_f_string = ",".join(included_disabled_features)
edge_options.add_argument("--disable-features=%s" % d_f_string)
if (set_binary or IS_LINUX) and not binary_location:
br_app = "edge"
binary_loc = detect_b_ver.get_binary_location(br_app)
if os.path.exists(binary_loc):
binary_location = binary_loc
if binary_location:
edge_options.binary_location = binary_location
service = EdgeService(
executable_path=LOCAL_EDGEDRIVER,
log_output=os.devnull,
service_args=["--disable-build-check"],
)
try:
driver = Edge(service=service, options=edge_options)
except Exception as e:
if not hasattr(e, "msg"):
raise
auto_upgrade_edgedriver = False
edge_version = None
if (
"This version of MSEdgeDriver only supports" in e.msg
or "This version of Microsoft Edge WebDriver" in e.msg
):
if "Current browser version is " in e.msg:
auto_upgrade_edgedriver = True
edge_version = e.msg.split(
"Current browser version is "
)[1].split(" ")[0]
elif "only supports MSEdge version " in e.msg:
auto_upgrade_edgedriver = True
edge_version = e.msg.split(
"only supports MSEdge version "
)[1].split(" ")[0]
elif "DevToolsActivePort file doesn't exist" in e.msg:
# https://stackoverflow.com/a/56638103/7058266
args = " ".join(sys.argv)
free_port = 9222
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
free_port = service_utils.free_port()
edge_options.add_argument(
"--remote-debugging-port=%s" % free_port
)
driver = Edge(service=service, options=edge_options)
return extend_driver(driver)
if not auto_upgrade_edgedriver:
raise # Not an obvious fix.
else:
pass # Try upgrading EdgeDriver to match Edge.
args = " ".join(sys.argv)
if "-n" in sys.argv or " -n=" in args or args == "-c":
edgedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with edgedriver_fixing_lock:
try:
if not _was_driver_repaired():
_repair_edgedriver(edge_version)
_mark_driver_repaired()
except Exception:
pass
else:
try:
if not _was_driver_repaired():
_repair_edgedriver(edge_version)
_mark_driver_repaired()
except Exception:
pass
driver = Edge(service=service, options=edge_options)
return extend_driver(driver)
elif browser_name == constants.Browser.SAFARI:
args = " ".join(sys.argv)
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
# Skip if multithreaded
raise Exception("Can't run Safari tests in multithreaded mode!")
warnings.simplefilter("ignore", category=DeprecationWarning)
from selenium.webdriver.safari.options import Options as SafariOptions
service = SafariService(quiet=False)
options = SafariOptions()
if (
page_load_strategy
and page_load_strategy.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
options.page_load_strategy = page_load_strategy.lower()
elif (
not page_load_strategy
and hasattr(settings, "PAGE_LOAD_STRATEGY")
and settings.PAGE_LOAD_STRATEGY
and settings.PAGE_LOAD_STRATEGY.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
options.page_load_strategy = settings.PAGE_LOAD_STRATEGY.lower()
driver = webdriver.safari.webdriver.WebDriver(
service=service, options=options
)
return extend_driver(driver)
elif browser_name == constants.Browser.GOOGLE_CHROME:
try:
chrome_options = _set_chrome_options(
browser_name,
downloads_path,
headless,
locale_code,
proxy_string,
proxy_auth,
proxy_user,
proxy_pass,
proxy_bypass_list,
proxy_pac_url,
multi_proxy,
user_agent,
recorder_ext,
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
undetectable,
uc_cdp_events,
uc_subprocess,
log_cdp_events,
no_sandbox,
disable_gpu,
headless2,
incognito,
guest_mode,
dark_mode,
devtools,
remote_debug,
enable_3d_apis,
swiftshader,
ad_block_on,
host_resolver_rules,
block_images,
do_not_track,
chromium_arg,
user_data_dir,
extension_zip,
extension_dir,
disable_features,
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
servername,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
use_version = "latest"
major_chrome_version = None
saved_mcv = None
full_ch_version = None
full_ch_driver_version = None
use_br_version_for_uc = False
try:
if chrome_options.binary_location:
try:
major_chrome_version = (
detect_b_ver.get_browser_version_from_binary(
chrome_options.binary_location,
)
)
saved_mcv = major_chrome_version
major_chrome_version = saved_mcv.split(".")[0]
if len(major_chrome_version) < 2:
major_chrome_version = None
except Exception:
major_chrome_version = None
if not major_chrome_version:
br_app = "google-chrome"
full_ch_version = (
detect_b_ver.get_browser_version_from_os(br_app)
)
saved_mcv = full_ch_version
major_chrome_version = full_ch_version.split(".")[0]
if int(major_chrome_version) < 67:
major_chrome_version = None
elif (
int(major_chrome_version) >= 67
and int(major_chrome_version) <= 72
):
# chromedrivers 2.41 - 2.46 could be swapped with 72
major_chrome_version = "72"
elif int(major_chrome_version) >= 115:
if (
driver_version == "browser"
and saved_mcv
and len(saved_mcv.split(".")) == 4
):
driver_version = saved_mcv
if is_using_uc(undetectable, browser_name):
use_br_version_for_uc = True
if (
(headless or headless2)
and IS_WINDOWS
and major_chrome_version
and int(major_chrome_version) >= 117
and not is_using_uc(undetectable, browser_name)
and not (remote_debug or devtools or use_wire)
and not (proxy_string or multi_proxy or proxy_pac_url)
and (not chromium_arg or "debug" not in chromium_arg)
and (not servername or servername == "localhost")
):
# Hide the "DevTools listening on ..." message.
# https://bugs.chromium.org
# /p/chromedriver/issues/detail?id=4403#c35
# (Only when the remote debugging port is not needed.)
chrome_options.add_argument("--remote-debugging-pipe")
except Exception:
major_chrome_version = None
if major_chrome_version:
use_version = major_chrome_version
ch_driver_version = None
path_chromedriver = chromedriver_on_path()
if os.path.exists(LOCAL_CHROMEDRIVER):
try:
output = subprocess.check_output(
'"%s" --version' % LOCAL_CHROMEDRIVER, shell=True
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
full_ch_driver_version = output.split(" ")[1]
output = full_ch_driver_version.split(".")[0]
if int(output) >= 2:
ch_driver_version = output
if driver_version == "keep":
driver_version = ch_driver_version
except Exception:
pass
elif path_chromedriver:
try:
make_driver_executable_if_not(path_chromedriver)
except Exception as e:
logging.debug(
"\nWarning: Could not make chromedriver"
" executable: %s" % e
)
try:
output = subprocess.check_output(
'"%s" --version' % path_chromedriver, shell=True
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
full_ch_driver_version = output.split(" ")[1]
output = full_ch_driver_version.split(".")[0]
if int(output) >= 2:
ch_driver_version = output
if driver_version == "keep":
use_version = ch_driver_version
except Exception:
pass
disable_build_check = True
uc_driver_version = None
if is_using_uc(undetectable, browser_name):
if use_br_version_for_uc or driver_version == "mlatest":
uc_driver_version = get_uc_driver_version(full=True)
full_ch_driver_version = uc_driver_version
else:
uc_driver_version = get_uc_driver_version()
if multi_proxy:
sb_config.multi_proxy = True
if uc_driver_version and driver_version == "keep":
driver_version = uc_driver_version
use_version = find_chromedriver_version_to_use(
use_version, driver_version
)
if headless2:
try:
if (
use_version == "latest"
or int(str(use_version).split(".")[0]) >= 109
):
chrome_options.add_argument("--headless=new")
else:
chrome_options.add_argument("--headless=chrome")
except Exception:
chrome_options.add_argument("--headless=new")
elif headless and undetectable:
try:
int_use_version = int(str(use_version).split(".")[0])
if int_use_version >= 109:
chrome_options.add_argument("--headless=new")
elif (
int_use_version >= 96
and int_use_version <= 108
):
chrome_options.add_argument("--headless=chrome")
else:
pass # Will need Xvfb on Linux
except Exception:
pass # Will need Xvfb on Linux
elif headless:
if "--headless" not in chrome_options.arguments:
chrome_options.add_argument("--headless")
if LOCAL_CHROMEDRIVER and os.path.exists(LOCAL_CHROMEDRIVER):
try:
make_driver_executable_if_not(LOCAL_CHROMEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make chromedriver"
" executable: %s" % e
)
use_uc = is_using_uc(undetectable, browser_name)
make_uc_driver_from_chromedriver = False
local_ch_exists = (
LOCAL_CHROMEDRIVER and os.path.exists(LOCAL_CHROMEDRIVER)
)
"""If no LOCAL_CHROMEDRIVER, but path_chromedriver, and the
browser version nearly matches the driver version, then use
the path_chromedriver instead of downloading a new driver.
Eg. 116.0.* for both is close, but not 116.0.* and 116.1.*"""
browser_driver_close_match = False
if (
path_chromedriver
and full_ch_version
and full_ch_driver_version
):
full_ch_v_p = full_ch_version.split(".")[0:2]
full_ch_driver_v_p = full_ch_driver_version.split(".")[0:2]
if (
full_ch_v_p == full_ch_driver_v_p
or driver_version == "keep"
):
browser_driver_close_match = True
# If not ARM MAC and need to use uc_driver (and it's missing),
# and already have chromedriver with the correct version,
# then copy chromedriver to uc_driver (and it'll get patched).
if (
not IS_ARM_MAC
and use_uc
and (
(
(local_ch_exists or path_chromedriver)
and use_version == ch_driver_version
and (
not os.path.exists(LOCAL_UC_DRIVER)
or uc_driver_version != use_version
)
)
or (
local_ch_exists
and use_version == "latest"
and not os.path.exists(LOCAL_UC_DRIVER)
)
)
):
make_uc_driver_from_chromedriver = True
elif (
(use_uc and not os.path.exists(LOCAL_UC_DRIVER))
or (not use_uc and not path_chromedriver)
or (
not use_uc
and use_version != "latest" # Browser version detected
and (ch_driver_version or not local_ch_exists)
and (
use_version.split(".")[0] != ch_driver_version
or (
not local_ch_exists
and use_version.isnumeric()
and int(use_version) >= 115
and not browser_driver_close_match
)
)
)
or (
use_uc
and use_version != "latest" # Browser version detected
and uc_driver_version != use_version
)
or (
full_ch_driver_version # Also used for the uc_driver
and driver_version
and len(str(driver_version).split(".")) == 4
and full_ch_driver_version != driver_version
)
):
# chromedriver download needed in the seleniumbase/drivers dir
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
msg = "chromedriver update needed. Getting it now:"
if not path_chromedriver:
msg = "chromedriver not found. Getting it now:"
if use_uc and not os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver not found. Getting it now:"
if use_uc and os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver update needed. Getting it now:"
log_d("\nWarning: %s" % msg)
force_uc = False
intel_for_uc = False
if use_uc:
force_uc = True
if IS_ARM_MAC and use_uc:
intel_for_uc = True # Use Intel's driver for UC Mode
try:
sb_install.main(
override="chromedriver %s" % use_version,
intel_for_uc=intel_for_uc,
force_uc=force_uc,
)
except Exception:
d_latest = get_latest_chromedriver_version()
if (
d_latest
and use_version != "latest"
and int(use_version) > int(d_latest.split(".")[0])
):
disable_build_check = True
d_latest_major = d_latest.split(".")[0]
if (
not path_chromedriver
or (
ch_driver_version
and (
int(ch_driver_version)
< int(d_latest_major)
)
)
):
sb_install.main(override="chromedriver latest")
sys.argv = sys_args # Put back the original sys args
else:
# (Multithreaded)
chromedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with chromedriver_fixing_lock:
msg = "chromedriver update needed. Getting it now:"
if not path_chromedriver:
msg = "chromedriver not found. Getting it now:"
if use_uc and not os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver not found. Getting it now:"
if use_uc and os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver update needed. Getting it now:"
force_uc = False
intel_for_uc = False
if use_uc:
force_uc = True
if IS_ARM_MAC and use_uc:
intel_for_uc = True # Use Intel driver for UC Mode
if os.path.exists(LOCAL_CHROMEDRIVER):
try:
output = subprocess.check_output(
'"%s" --version' % LOCAL_CHROMEDRIVER,
shell=True,
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
full_ch_driver_version = output.split(" ")[1]
output = full_ch_driver_version.split(".")[0]
if int(output) >= 2:
ch_driver_version = output
except Exception:
pass
if (
(
not use_uc
and not os.path.exists(LOCAL_CHROMEDRIVER)
)
or (use_uc and not os.path.exists(LOCAL_UC_DRIVER))
or (
not use_uc
and (
use_version.split(".")[0]
!= ch_driver_version
)
)
or (
use_uc
and (
use_version.split(".")[0]
!= get_uc_driver_version()
)
)
):
log_d("\nWarning: %s" % msg)
sys_args = sys.argv # Save a copy of sys args
try:
sb_install.main(
override="chromedriver %s" % use_version,
intel_for_uc=intel_for_uc,
force_uc=force_uc,
)
except Exception:
d_latest = get_latest_chromedriver_version()
if (
d_latest
and use_version != "latest"
and (
int(use_version)
> int(d_latest.split(".")[0])
)
):
disable_build_check = True
d_latest_major = d_latest.split(".")[0]
if (
not path_chromedriver
or (
ch_driver_version
and (
int(ch_driver_version)
< int(d_latest_major)
)
)
):
sb_install.main(
override="chromedriver latest"
)
finally:
sys.argv = sys_args # Put back original args
service_args = []
if disable_build_check:
service_args = ["--disable-build-check"]
if is_using_uc(undetectable, browser_name):
uc_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with uc_lock: # Avoid multithreaded issues
if make_uc_driver_from_chromedriver:
if os.path.exists(LOCAL_CHROMEDRIVER):
shutil.copyfile(
LOCAL_CHROMEDRIVER, LOCAL_UC_DRIVER
)
elif os.path.exists(path_chromedriver):
shutil.copyfile(
path_chromedriver, LOCAL_UC_DRIVER
)
try:
make_driver_executable_if_not(LOCAL_UC_DRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make uc_driver"
" executable: %s" % e
)
if (
not headless
or not IS_LINUX
or is_using_uc(undetectable, browser_name)
):
uc_activated = False
try:
if (
os.path.exists(LOCAL_CHROMEDRIVER)
or is_using_uc(undetectable, browser_name)
):
if headless and not IS_LINUX:
undetectable = False # No support for headless
if is_using_uc(undetectable, browser_name):
from seleniumbase import undetected
from urllib.error import URLError
if IS_LINUX:
if "--headless" in (
chrome_options.arguments
):
chrome_options.arguments.remove(
"--headless"
)
uc_chrome_version = None
if (
use_version.isnumeric()
and int(use_version) >= 72
):
uc_chrome_version = int(use_version)
elif (
str(use_version).split(".")[0].isnumeric()
and int(str(use_version).split(".")[0]) >= 72
):
uc_chrome_version = (
int(str(use_version).split(".")[0])
)
cdp_events = uc_cdp_events
cert = "unable to get local issuer certificate"
mac_certificate_error = False
if (
use_version.isnumeric()
and int(use_version) <= 74
):
chrome_options.add_experimental_option(
"w3c", True
)
if (
(not user_agent or "Headless" in user_agent)
and uc_chrome_version
and uc_chrome_version >= 117
and (headless or headless2)
and hasattr(sb_config, "uc_agent_cache")
):
user_agent = sb_config.uc_agent_cache
chrome_options.add_argument(
"--user-agent=%s" % user_agent
)
try:
if (
(
not user_agent
or "Headless" in user_agent
)
and uc_chrome_version
and uc_chrome_version >= 117
and (headless or headless2)
):
from seleniumbase.console_scripts import (
sb_install
)
sb_config.uc_user_agent_cache = True
headless_options = _set_chrome_options(
browser_name,
downloads_path,
True, # headless
locale_code,
None, # proxy_string
None, # proxy_auth
None, # proxy_user
None, # proxy_pass
None, # proxy_bypass_list
None, # proxy_pac_url
None, # multi_proxy
None, # user_agent
None, # recorder_ext
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
False, # undetectable
False, # uc_cdp_events
False, # uc_subprocess
False, # log_cdp_events
no_sandbox,
disable_gpu,
False, # headless2
incognito,
guest_mode,
dark_mode,
None, # devtools
remote_debug,
enable_3d_apis,
swiftshader,
None, # ad_block_on
None, # host_resolver_rules
block_images,
do_not_track,
None, # chromium_arg
None, # user_data_dir
None, # extension_zip
None, # extension_dir
None, # disable_features
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
servername,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
if (
not path_chromedriver
or (
ch_driver_version
and use_version
and (
int(ch_driver_version)
< int(str(
use_version).split(".")[0]
)
)
)
):
sb_install.main(
override="chromedriver %s"
% use_version,
intel_for_uc=False,
force_uc=False,
)
d_b_c = "--disable-build-check"
if os.path.exists(LOCAL_CHROMEDRIVER):
service = ChromeService(
executable_path=LOCAL_CHROMEDRIVER,
log_output=os.devnull,
service_args=[d_b_c],
)
driver = webdriver.Chrome(
service=service,
options=headless_options,
)
else:
service = ChromeService(
log_output=os.devnull,
service_args=[d_b_c],
)
driver = webdriver.Chrome(
service=service,
options=headless_options,
)
try:
user_agent = driver.execute_script(
"return navigator.userAgent;"
)
if (
major_chrome_version
and full_ch_version
and full_ch_version.count(".") == 3
and full_ch_version in user_agent
):
mcv = major_chrome_version
user_agent = user_agent.replace(
"Chrome/%s" % full_ch_version,
"Chrome/%s.0.0.0" % mcv
)
user_agent = user_agent.replace(
"Headless", ""
)
chrome_options.add_argument(
"--user-agent=%s" % user_agent
)
sb_config.uc_agent_cache = user_agent
except Exception:
pass
driver.quit()
except Exception:
pass
uc_path = None
if os.path.exists(LOCAL_UC_DRIVER):
uc_path = LOCAL_UC_DRIVER
uc_path = os.path.realpath(uc_path)
try:
driver = undetected.Chrome(
options=chrome_options,
user_data_dir=user_data_dir,
driver_executable_path=uc_path,
browser_executable_path=b_path,
enable_cdp_events=cdp_events,
headless=False, # Xvfb needed!
version_main=uc_chrome_version,
use_subprocess=True, # Always!
)
uc_activated = True
except URLError as e:
if cert in e.args[0] and IS_MAC:
mac_certificate_error = True
else:
raise
except SessionNotCreatedException:
time.sleep(0.2)
driver = undetected.Chrome(
options=chrome_options,
user_data_dir=user_data_dir,
driver_executable_path=uc_path,
browser_executable_path=b_path,
enable_cdp_events=cdp_events,
headless=False, # Xvfb needed!
version_main=uc_chrome_version,
use_subprocess=True, # Always!
)
uc_activated = True
if mac_certificate_error:
cf_lock_path = (
constants.MultiBrowser.CERT_FIXING_LOCK
)
cf_lock = fasteners.InterProcessLock(
constants.MultiBrowser.CERT_FIXING_LOCK
)
if not os.path.exists(cf_lock_path):
# Avoid multithreaded issues
with cf_lock:
# Install Python Certificates (MAC)
os.system(
r"bash /Applications/Python*/"
r"Install\ "
r"Certificates.command"
)
driver = undetected.Chrome(
options=chrome_options,
user_data_dir=user_data_dir,
driver_executable_path=uc_path,
browser_executable_path=b_path,
enable_cdp_events=cdp_events,
headless=False, # Xvfb needed!
version_main=uc_chrome_version,
use_subprocess=True, # Always!
)
uc_activated = True
else:
if (
use_version.isnumeric()
and int(use_version) <= 74
):
chrome_options.add_experimental_option(
"w3c", True
)
service = ChromeService(
executable_path=LOCAL_CHROMEDRIVER,
log_output=os.devnull,
service_args=service_args,
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
else:
service = ChromeService(
log_output=os.devnull,
service_args=service_args,
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
except Exception as e:
if not hasattr(e, "msg"):
raise
auto_upgrade_chromedriver = False
if "This version of ChromeDriver only supports" in e.msg:
auto_upgrade_chromedriver = True
elif "Chrome version must be between" in e.msg:
auto_upgrade_chromedriver = True
elif "Missing or invalid capabilities" in e.msg:
chrome_options.add_experimental_option("w3c", True)
service = ChromeService(
log_output=os.devnull,
service_args=service_args,
)
with warnings.catch_warnings():
warnings.simplefilter(
"ignore", category=DeprecationWarning
)
driver = webdriver.Chrome(
service=service, options=chrome_options
)
return extend_driver(driver)
if not auto_upgrade_chromedriver:
raise # Not an obvious fix.
else:
pass # Try upgrading ChromeDriver to match Chrome.
mcv = None # Major Chrome Version
if "Current browser version is " in e.msg:
line = e.msg.split("Current browser version is ")[1]
browser_version = line.split(" ")[0]
major_chrome_version = browser_version.split(".")[0]
if (
major_chrome_version.isnumeric()
and int(major_chrome_version) >= 86
):
mcv = major_chrome_version
mcv = find_chromedriver_version_to_use(
mcv, driver_version
)
headless_options = _set_chrome_options(
browser_name,
downloads_path,
True, # headless
locale_code,
None, # proxy_string
None, # proxy_auth
None, # proxy_user
None, # proxy_pass
None, # proxy_bypass_list
None, # proxy_pac_url
None, # multi_proxy
None, # user_agent
None, # recorder_ext
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
False, # undetectable
False, # uc_cdp_events
False, # uc_subprocess
False, # log_cdp_events
no_sandbox,
disable_gpu,
False, # headless2
incognito,
guest_mode,
dark_mode,
None, # devtools
remote_debug,
enable_3d_apis,
swiftshader,
None, # ad_block_on
None, # host_resolver_rules
block_images,
do_not_track,
None, # chromium_arg
None, # user_data_dir
None, # extension_zip
None, # extension_dir
None, # disable_features
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
servername,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
args = " ".join(sys.argv)
if "-n" in sys.argv or " -n=" in args or args == "-c":
chromedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with chromedriver_fixing_lock:
if not _was_driver_repaired():
_repair_chromedriver(
chrome_options, headless_options, mcv
)
_mark_driver_repaired()
else:
if not _was_driver_repaired():
_repair_chromedriver(
chrome_options, headless_options, mcv
)
_mark_driver_repaired()
if os.path.exists(LOCAL_CHROMEDRIVER):
service = ChromeService(
executable_path=LOCAL_CHROMEDRIVER,
log_output=os.devnull,
service_args=["--disable-build-check"],
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
else:
service = ChromeService(
log_output=os.devnull,
service_args=["--disable-build-check"],
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
driver.default_get = driver.get # Save copy of original
if uc_activated:
driver.get = lambda url: uc_special_open_if_cf(
driver,
url,
proxy_string,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
driver.uc_open = lambda url: uc_open(driver, url)
driver.uc_open_with_tab = (
lambda url: uc_open_with_tab(driver, url)
)
driver.uc_open_with_reconnect = (
lambda *args, **kwargs: uc_open_with_reconnect(
driver, *args, **kwargs
)
)
driver.uc_open_with_disconnect = (
lambda *args, **kwargs: uc_open_with_disconnect(
driver, *args, **kwargs
)
)
driver.uc_click = lambda *args, **kwargs: uc_click(
driver, *args, **kwargs
)
driver.uc_gui_press_key = (
lambda *args, **kwargs: uc_gui_press_key(
driver, *args, **kwargs
)
)
driver.uc_gui_press_keys = (
lambda *args, **kwargs: uc_gui_press_keys(
driver, *args, **kwargs
)
)
driver.uc_gui_write = (
lambda *args, **kwargs: uc_gui_write(
driver, *args, **kwargs
)
)
driver.uc_gui_click_x_y = (
lambda *args, **kwargs: uc_gui_click_x_y(
driver, *args, **kwargs
)
)
driver.uc_gui_click_captcha = (
lambda *args, **kwargs: uc_gui_click_captcha(
driver, *args, **kwargs
)
)
driver.uc_gui_click_cf = (
lambda *args, **kwargs: uc_gui_click_cf(
driver, *args, **kwargs
)
)
driver.uc_gui_click_rc = (
lambda *args, **kwargs: uc_gui_click_rc(
driver, *args, **kwargs
)
)
driver.uc_gui_handle_captcha = (
lambda *args, **kwargs: uc_gui_handle_captcha(
driver, *args, **kwargs
)
)
driver.uc_gui_handle_cf = (
lambda *args, **kwargs: uc_gui_handle_cf(
driver, *args, **kwargs
)
)
driver.uc_gui_handle_rc = (
lambda *args, **kwargs: uc_gui_handle_rc(
driver, *args, **kwargs
)
)
driver.uc_switch_to_frame = (
lambda *args, **kwargs: uc_switch_to_frame(
driver, *args, **kwargs
)
)
driver._is_hidden = (headless or headless2)
driver._is_using_uc = True
if mobile_emulator:
uc_metrics = {}
if (
isinstance(device_width, int)
and isinstance(device_height, int)
and isinstance(device_pixel_ratio, (int, float))
):
uc_metrics["width"] = device_width
uc_metrics["height"] = device_height
uc_metrics["pixelRatio"] = device_pixel_ratio
else:
uc_metrics["width"] = constants.Mobile.WIDTH
uc_metrics["height"] = constants.Mobile.HEIGHT
uc_metrics["pixelRatio"] = constants.Mobile.RATIO
set_device_metrics_override = dict(
{
"width": uc_metrics["width"],
"height": uc_metrics["height"],
"deviceScaleFactor": uc_metrics["pixelRatio"],
"mobile": True
}
)
try:
driver.execute_cdp_cmd(
'Emulation.setDeviceMetricsOverride',
set_device_metrics_override
)
except Exception:
pass
return extend_driver(driver)
else: # Running headless on Linux (and not using --uc)
try:
> driver = webdriver.Chrome(options=chrome_options)

/usr/local/lib/python3.10/dist-packages/seleniumbase/core/browser_launcher.py:4613:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chrome/webdriver.py:45: in __init__
super().__init__(
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chromium/webdriver.py:50: in __init__
if finder.get_browser_path():
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:47: in get_browser_path
return self._binary_paths()["browser_path"]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f5289abdc0>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
output = SeleniumManager().binary_paths(self._to_args())
if Path(output["driver_path"]).is_file():
self._paths["driver_path"] = output["driver_path"]
else:
raise ValueError(f'The driver path is not a valid file: {output["driver_path"]}')
if Path(output["browser_path"]).is_file():
self._paths["browser_path"] = output["browser_path"]
else:
raise ValueError(f'The browser path is not a valid file: {output["browser_path"]}')
except Exception as err:
msg = f"Unable to obtain driver for {browser}"
> raise NoSuchDriverException(msg) from err
E selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for chrome; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:78: NoSuchDriverException

During handling of the above exception, another exception occurred:

args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
> completed_proc = subprocess.run(args, capture_output=True)

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:116:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.10/subprocess.py:503: in run
with Popen(*popenargs, **kwargs) as process:
/usr/lib/python3.10/subprocess.py:971: in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <Popen: returncode: None args: ['/usr/local/lib/python3.10/dist-packages/sel...>
args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]
executable = b'/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager'
preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None
startupinfo = None, creationflags = 0, shell = False, p2cread = -1
p2cwrite = -1, c2pread = 15, c2pwrite = 18, errread = 19, errwrite = 20
restore_signals = True, gid = None, gids = None, uid = None, umask = -1
start_new_session = False

def _execute_child(self, args, executable, preexec_fn, close_fds,
pass_fds, cwd, env,
startupinfo, creationflags, shell,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite,
restore_signals,
gid, gids, uid, umask,
start_new_session):
"""Execute program (POSIX version)"""

if isinstance(args, (str, bytes)):
args = [args]
elif isinstance(args, os.PathLike):
if shell:
raise TypeError('path-like args is not allowed when '
'shell is true')
args = [args]
else:
args = list(args)

if shell:
# On Android the default shell is at '/system/bin/sh'.
unix_shell = ('/system/bin/sh' if
hasattr(sys, 'getandroidapilevel') else '/bin/sh')
args = [unix_shell, "-c"] + args
if executable:
args[0] = executable

if executable is None:
executable = args[0]

sys.audit("subprocess.Popen", executable, args, cwd, env)

if (_USE_POSIX_SPAWN
and os.path.dirname(executable)
and preexec_fn is None
and not close_fds
and not pass_fds
and cwd is None
and (p2cread == -1 or p2cread > 2)
and (c2pwrite == -1 or c2pwrite > 2)
and (errwrite == -1 or errwrite > 2)
and not start_new_session
and gid is None
and gids is None
and uid is None
and umask < 0):
self._posix_spawn(args, executable, env, restore_signals,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite)
return

orig_executable = executable

# For transferring possible exec failure from child to parent.
# Data format: "exception name:hex errno:description"
# Pickle is not used; it is complex and involves memory allocation.
errpipe_read, errpipe_write = os.pipe()
# errpipe_write must not be in the standard io 0, 1, or 2 fd range.
low_fds_to_close = []
while errpipe_write < 3:
low_fds_to_close.append(errpipe_write)
errpipe_write = os.dup(errpipe_write)
for low_fd in low_fds_to_close:
os.close(low_fd)
try:
try:
# We must avoid complex work that could involve
# malloc or free in the child process to avoid
# potential deadlocks, thus we do all this here.
# and pass it to fork_exec()

if env is not None:
env_list = []
for k, v in env.items():
k = os.fsencode(k)
if b'=' in k:
raise ValueError("illegal environment variable name")
env_list.append(k + b'=' + os.fsencode(v))
else:
env_list = None # Use execv instead of execve.
executable = os.fsencode(executable)
if os.path.dirname(executable):
executable_list = (executable,)
else:
# This matches the behavior of os._execvpe().
executable_list = tuple(
os.path.join(os.fsencode(dir), executable)
for dir in os.get_exec_path(env))
fds_to_keep = set(pass_fds)
fds_to_keep.add(errpipe_write)
> self.pid = _posixsubprocess.fork_exec(
args, executable_list,
close_fds, tuple(sorted(map(int, fds_to_keep))),
cwd, env_list,
p2cread, p2cwrite, c2pread, c2pwrite,
errread, errwrite,
errpipe_read, errpipe_write,
restore_signals, start_new_session,
gid, gids, uid, umask,
preexec_fn)
E BlockingIOError: [Errno 11] Resource temporarily unavailable

/usr/lib/python3.10/subprocess.py:1796: BlockingIOError

The above exception was the direct cause of the following exception:

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f5289abc70>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
> output = SeleniumManager().binary_paths(self._to_args())

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:67:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:54: in binary_paths
return self._run(args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
completed_proc = subprocess.run(args, capture_output=True)
stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")
stderr = completed_proc.stderr.decode("utf-8").rstrip("\n")
output = json.loads(stdout) if stdout != "" else {"logs": [], "result": {}}
except Exception as err:
> raise WebDriverException(f"Unsuccessful command executed: {command}") from err
E selenium.common.exceptions.WebDriverException: Message: Unsuccessful command executed: /usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager --browser chrome --language-binding python --output json

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:121: WebDriverException

The above exception was the direct cause of the following exception:
/usr/local/lib/python3.10/dist-packages/seleniumbase/fixtures/base_case.py:14917: in setUp
self.driver = self.get_new_driver(
/usr/local/lib/python3.10/dist-packages/seleniumbase/fixtures/base_case.py:4101: in get_new_driver
new_driver = browser_launcher.get_driver(
/usr/local/lib/python3.10/dist-packages/seleniumbase/core/browser_launcher.py:2339: in get_driver
return get_local_driver(
/usr/local/lib/python3.10/dist-packages/seleniumbase/core/browser_launcher.py:4695: in get_local_driver
driver = webdriver.Chrome(
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chrome/webdriver.py:45: in __init__
super().__init__(
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chromium/webdriver.py:50: in __init__
if finder.get_browser_path():
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:47: in get_browser_path
return self._binary_paths()["browser_path"]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f5289abc70>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
output = SeleniumManager().binary_paths(self._to_args())
if Path(output["driver_path"]).is_file():
self._paths["driver_path"] = output["driver_path"]
else:
raise ValueError(f'The driver path is not a valid file: {output["driver_path"]}')
if Path(output["browser_path"]).is_file():
self._paths["browser_path"] = output["browser_path"]
else:
raise ValueError(f'The browser path is not a valid file: {output["browser_path"]}')
except Exception as err:
msg = f"Unable to obtain driver for {browser}"
> raise NoSuchDriverException(msg) from err
E selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for chrome; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:78: NoSuchDriverException
Failed FOrUS_testing.py::FOrusWebsite::test_open_webiste_and_accept_cookies 0.16
args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
> completed_proc = subprocess.run(args, capture_output=True)

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:116:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.10/subprocess.py:503: in run
with Popen(*popenargs, **kwargs) as process:
/usr/lib/python3.10/subprocess.py:971: in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <Popen: returncode: None args: ['/usr/local/lib/python3.10/dist-packages/sel...>
args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]
executable = b'/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager'
preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None
startupinfo = None, creationflags = 0, shell = False, p2cread = -1
p2cwrite = -1, c2pread = 15, c2pwrite = 18, errread = 19, errwrite = 20
restore_signals = True, gid = None, gids = None, uid = None, umask = -1
start_new_session = False

def _execute_child(self, args, executable, preexec_fn, close_fds,
pass_fds, cwd, env,
startupinfo, creationflags, shell,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite,
restore_signals,
gid, gids, uid, umask,
start_new_session):
"""Execute program (POSIX version)"""

if isinstance(args, (str, bytes)):
args = [args]
elif isinstance(args, os.PathLike):
if shell:
raise TypeError('path-like args is not allowed when '
'shell is true')
args = [args]
else:
args = list(args)

if shell:
# On Android the default shell is at '/system/bin/sh'.
unix_shell = ('/system/bin/sh' if
hasattr(sys, 'getandroidapilevel') else '/bin/sh')
args = [unix_shell, "-c"] + args
if executable:
args[0] = executable

if executable is None:
executable = args[0]

sys.audit("subprocess.Popen", executable, args, cwd, env)

if (_USE_POSIX_SPAWN
and os.path.dirname(executable)
and preexec_fn is None
and not close_fds
and not pass_fds
and cwd is None
and (p2cread == -1 or p2cread > 2)
and (c2pwrite == -1 or c2pwrite > 2)
and (errwrite == -1 or errwrite > 2)
and not start_new_session
and gid is None
and gids is None
and uid is None
and umask < 0):
self._posix_spawn(args, executable, env, restore_signals,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite)
return

orig_executable = executable

# For transferring possible exec failure from child to parent.
# Data format: "exception name:hex errno:description"
# Pickle is not used; it is complex and involves memory allocation.
errpipe_read, errpipe_write = os.pipe()
# errpipe_write must not be in the standard io 0, 1, or 2 fd range.
low_fds_to_close = []
while errpipe_write < 3:
low_fds_to_close.append(errpipe_write)
errpipe_write = os.dup(errpipe_write)
for low_fd in low_fds_to_close:
os.close(low_fd)
try:
try:
# We must avoid complex work that could involve
# malloc or free in the child process to avoid
# potential deadlocks, thus we do all this here.
# and pass it to fork_exec()

if env is not None:
env_list = []
for k, v in env.items():
k = os.fsencode(k)
if b'=' in k:
raise ValueError("illegal environment variable name")
env_list.append(k + b'=' + os.fsencode(v))
else:
env_list = None # Use execv instead of execve.
executable = os.fsencode(executable)
if os.path.dirname(executable):
executable_list = (executable,)
else:
# This matches the behavior of os._execvpe().
executable_list = tuple(
os.path.join(os.fsencode(dir), executable)
for dir in os.get_exec_path(env))
fds_to_keep = set(pass_fds)
fds_to_keep.add(errpipe_write)
> self.pid = _posixsubprocess.fork_exec(
args, executable_list,
close_fds, tuple(sorted(map(int, fds_to_keep))),
cwd, env_list,
p2cread, p2cwrite, c2pread, c2pwrite,
errread, errwrite,
errpipe_read, errpipe_write,
restore_signals, start_new_session,
gid, gids, uid, umask,
preexec_fn)
E BlockingIOError: [Errno 11] Resource temporarily unavailable

/usr/lib/python3.10/subprocess.py:1796: BlockingIOError

The above exception was the direct cause of the following exception:

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f523ea6890>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
> output = SeleniumManager().binary_paths(self._to_args())

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:67:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:54: in binary_paths
return self._run(args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
completed_proc = subprocess.run(args, capture_output=True)
stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")
stderr = completed_proc.stderr.decode("utf-8").rstrip("\n")
output = json.loads(stdout) if stdout != "" else {"logs": [], "result": {}}
except Exception as err:
> raise WebDriverException(f"Unsuccessful command executed: {command}") from err
E selenium.common.exceptions.WebDriverException: Message: Unsuccessful command executed: /usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager --browser chrome --language-binding python --output json

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:121: WebDriverException

The above exception was the direct cause of the following exception:

browser_name = 'chrome', headless = True, locale_code = None
servername = 'localhost', proxy_string = None, proxy_auth = False
proxy_user = None, proxy_pass = None, proxy_bypass_list = None
proxy_pac_url = None, multi_proxy = False, user_agent = None
recorder_ext = False, disable_js = False, disable_csp = False, enable_ws = True
enable_sync = False, use_auto_ext = False, undetectable = False
uc_cdp_events = None, uc_subprocess = None, log_cdp_events = None
no_sandbox = False, disable_gpu = False, headless2 = False, incognito = False
guest_mode = False, dark_mode = False, devtools = False, remote_debug = False
enable_3d_apis = False, swiftshader = False, ad_block_on = False
host_resolver_rules = None, block_images = False, do_not_track = False
chromium_arg = None, firefox_arg = None, firefox_pref = None
user_data_dir = None, extension_zip = None, extension_dir = None
disable_features = None, binary_location = None, driver_version = None
page_load_strategy = None, use_wire = False, external_pdf = False
mobile_emulator = False, device_width = None, device_height = None
device_pixel_ratio = None

def get_local_driver(
browser_name,
headless,
locale_code,
servername,
proxy_string,
proxy_auth,
proxy_user,
proxy_pass,
proxy_bypass_list,
proxy_pac_url,
multi_proxy,
user_agent,
recorder_ext,
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
undetectable,
uc_cdp_events,
uc_subprocess,
log_cdp_events,
no_sandbox,
disable_gpu,
headless2,
incognito,
guest_mode,
dark_mode,
devtools,
remote_debug,
enable_3d_apis,
swiftshader,
ad_block_on,
host_resolver_rules,
block_images,
do_not_track,
chromium_arg,
firefox_arg,
firefox_pref,
user_data_dir,
extension_zip,
extension_dir,
disable_features,
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
):
"""Spins up a new web browser and returns the driver.
Can also be used to spin up additional browsers for the same test."""
downloads_path = DOWNLOADS_FOLDER
b_path = binary_location
if use_wire:
pip_find_lock = fasteners.InterProcessLock(
constants.PipInstall.FINDLOCK
)
with pip_find_lock: # Prevent issues with multiple processes
try:
from seleniumwire import webdriver
import blinker
try:
use_blinker_ver = constants.SeleniumWire.BLINKER_VER
if blinker.__version__ != use_blinker_ver:
shared_utils.pip_install(
"blinker", version=use_blinker_ver
)
except Exception:
pass
del blinker
except Exception:
shared_utils.pip_install(
"blinker", version=constants.SeleniumWire.BLINKER_VER
)
shared_utils.pip_install(
"selenium-wire", version=constants.SeleniumWire.VER
)
from seleniumwire import webdriver
warnings.simplefilter("ignore", category=DeprecationWarning)
else:
from selenium import webdriver

if browser_name == constants.Browser.FIREFOX:
firefox_options = _set_firefox_options(
downloads_path,
headless,
locale_code,
proxy_string,
proxy_bypass_list,
proxy_pac_url,
user_agent,
disable_js,
disable_csp,
firefox_arg,
firefox_pref,
)
if LOCAL_GECKODRIVER and os.path.exists(LOCAL_GECKODRIVER):
try:
make_driver_executable_if_not(LOCAL_GECKODRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make geckodriver"
" executable: %s" % e
)
elif not geckodriver_on_path():
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
log_d("\nWarning: geckodriver not found. Getting it now:")
try:
sb_install.main(override="geckodriver")
except Exception as e:
log_d("\nWarning: Could not install geckodriver: %s" % e)
sys.argv = sys_args # Put back the original sys args
else:
geckodriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with geckodriver_fixing_lock:
if not geckodriver_on_path():
sys_args = sys.argv # Save a copy of sys args
log_d(
"\nWarning: geckodriver not found. "
"Getting it now:"
)
sb_install.main(override="geckodriver")
sys.argv = sys_args # Put back original sys args
# Launch Firefox
if os.path.exists(LOCAL_GECKODRIVER):
service = FirefoxService(
executable_path=LOCAL_GECKODRIVER,
log_output=os.devnull,
)
try:
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
except BaseException as e:
if (
"geckodriver unexpectedly exited" in str(e)
or "Process unexpectedly closed" in str(e)
or "Failed to read marionette port" in str(e)
or "A connection attempt failed" in str(e)
or "Expected browser binary" in str(e)
or hasattr(e, "msg") and (
"geckodriver unexpectedly exited" in e.msg
or "Process unexpectedly closed" in e.msg
or "Failed to read marionette port" in e.msg
or "A connection attempt failed" in e.msg
or "Expected browser binary" in e.msg
)
):
time.sleep(0.1)
if (
IS_LINUX
and headless
and (
"unexpected" in str(e)
or (
hasattr(e, "msg") and "unexpected" in e.msg
)
)
):
firefox_options.add_argument("-headless")
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
else:
raise # Not an obvious fix.
else:
service = FirefoxService(log_output=os.devnull)
try:
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
except BaseException as e:
if (
"geckodriver unexpectedly exited" in str(e)
or "Process unexpectedly closed" in str(e)
or "Failed to read marionette port" in str(e)
or "A connection attempt failed" in str(e)
or "Expected browser binary" in str(e)
or hasattr(e, "msg") and (
"geckodriver unexpectedly exited" in e.msg
or "Process unexpectedly closed" in e.msg
or "Failed to read marionette port" in e.msg
or "A connection attempt failed" in e.msg
or "Expected browser binary" in e.msg
)
):
time.sleep(0.1)
if (
IS_LINUX
and headless
and (
"unexpected" in str(e)
or (
hasattr(e, "msg") and "unexpected" in e.msg
)
)
):
firefox_options.add_argument("-headless")
driver = webdriver.Firefox(
service=service,
options=firefox_options,
)
return extend_driver(driver)
else:
raise # Not an obvious fix.
elif browser_name == constants.Browser.INTERNET_EXPLORER:
if not IS_WINDOWS:
raise Exception(
"IE Browser is for Windows-based systems only!"
)
from selenium.webdriver.ie.options import Options
from selenium.webdriver.ie.service import Service
ie_options = Options()
ie_options.add_argument("--guest")
ie_options.attach_to_edge_chrome = True
ie_options.ignore_protected_mode_settings = True
ie_options.ignore_zoom_level = True
ie_options.require_window_focus = False
ie_options.native_events = True
ie_options.full_page_screenshot = True
ie_options.persistent_hover = True
if LOCAL_IEDRIVER and os.path.exists(LOCAL_IEDRIVER):
try:
make_driver_executable_if_not(LOCAL_IEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make IEDriver executable: %s" % e
)
elif not iedriver_on_path():
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
log_d("\nWarning: IEDriver not found. Getting it now:")
sb_install.main(override="iedriver")
sys.argv = sys_args # Put back the original sys args
if LOCAL_HEADLESS_IEDRIVER and os.path.exists(LOCAL_HEADLESS_IEDRIVER):
try:
make_driver_executable_if_not(LOCAL_HEADLESS_IEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make HeadlessIEDriver executable: %s"
% e
)
elif not headless_iedriver_on_path():
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
log_d("\nWarning: HeadlessIEDriver not found. Getting it now:")
sb_install.main(override="iedriver")
sys.argv = sys_args # Put back the original sys args
d_b_c = "--disable-build-check"
logger = logging.getLogger("selenium")
logger.setLevel("INFO")
if not headless:
warnings.simplefilter("ignore", category=DeprecationWarning)
service = Service(service_args=[d_b_c], log_output=os.devnull)
driver = webdriver.Ie(service=service, options=ie_options)
return extend_driver(driver)
else:
warnings.simplefilter("ignore", category=DeprecationWarning)
service = Service(
executable_path=LOCAL_IEDRIVER,
service_args=[d_b_c],
log_output=os.devnull,
)
driver = webdriver.Ie(service=service, options=ie_options)
return extend_driver(driver)
elif browser_name == constants.Browser.EDGE:
prefs = {
"download.default_directory": downloads_path,
"download.directory_upgrade": True,
"download.prompt_for_download": False,
"credentials_enable_service": False,
"local_discovery.notifications_enabled": False,
"safebrowsing.disable_download_protection": True,
"safebrowsing.enabled": False, # Prevent PW "data breach" pop-ups
"omnibox-max-zero-suggest-matches": 0,
"omnibox-use-existing-autocomplete-client": 0,
"omnibox-trending-zero-prefix-suggestions-on-ntp": 0,
"omnibox-local-history-zero-suggest-beyond-ntp": 0,
"omnibox-on-focus-suggestions-contextual-web": 0,
"omnibox-on-focus-suggestions-srp": 0,
"omnibox-zero-suggest-prefetching": 0,
"omnibox-zero-suggest-prefetching-on-srp": 0,
"omnibox-zero-suggest-prefetching-on-web": 0,
"omnibox-zero-suggest-in-memory-caching": 0,
"content_settings.exceptions.automatic_downloads.*.setting": 1,
"default_content_setting_values.notifications": 0,
"default_content_settings.popups": 0,
"managed_default_content_settings.popups": 0,
"profile.password_manager_enabled": False,
"profile.default_content_setting_values.notifications": 2,
"profile.default_content_settings.popups": 0,
"profile.managed_default_content_settings.popups": 0,
"profile.default_content_setting_values.automatic_downloads": 1,
}
use_version = "latest"
major_edge_version = None
saved_mev = None
use_br_version_for_edge = False
use_exact_version_for_edge = False
try:
if binary_location:
try:
major_edge_version = (
detect_b_ver.get_browser_version_from_binary(
binary_location
)
)
saved_mev = major_edge_version
major_edge_version = saved_mev.split(".")[0]
if len(major_edge_version) < 2:
major_edge_version = None
except Exception:
major_edge_version = None
if not major_edge_version:
br_app = "edge"
major_edge_version = (
detect_b_ver.get_browser_version_from_os(br_app)
)
saved_mev = major_edge_version
major_edge_version = major_edge_version.split(".")[0]
if int(major_edge_version) < 80:
major_edge_version = None
elif int(major_edge_version) >= 115:
if (
driver_version == "browser"
and saved_mev
and len(saved_mev.split(".")) == 4
):
driver_version = saved_mev
use_br_version_for_edge = True
except Exception:
major_edge_version = None
if driver_version and "." in driver_version:
use_exact_version_for_edge = True
if use_br_version_for_edge:
major_edge_version = saved_mev
if major_edge_version:
use_version = major_edge_version
edge_driver_version = None
edgedriver_upgrade_needed = False
if os.path.exists(LOCAL_EDGEDRIVER):
try:
output = subprocess.check_output(
'"%s" --version' % LOCAL_EDGEDRIVER, shell=True
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
if output.split(" ")[0] == "MSEdgeDriver":
# MSEdgeDriver VERSION
output = output.split(" ")[1]
if use_exact_version_for_edge:
edge_driver_version = output.split(" ")[0]
output = output.split(".")[0]
elif output.split(" ")[0] == "Microsoft":
output = output.split(" ")[3]
if use_exact_version_for_edge:
edge_driver_version = output.split(" ")[0]
output = output.split(".")[0]
else:
output = 0
if int(output) >= 2:
if not use_exact_version_for_edge:
edge_driver_version = output
if driver_version == "keep":
driver_version = edge_driver_version
except Exception:
pass
use_version = find_edgedriver_version_to_use(
use_version, driver_version
)
local_edgedriver_exists = False
if LOCAL_EDGEDRIVER and os.path.exists(LOCAL_EDGEDRIVER):
local_edgedriver_exists = True
if (
use_version != "latest"
and edge_driver_version
and use_version != edge_driver_version
):
edgedriver_upgrade_needed = True
else:
try:
make_driver_executable_if_not(LOCAL_EDGEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make edgedriver"
" executable: %s" % e
)
if not local_edgedriver_exists or edgedriver_upgrade_needed:
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
msg = "Microsoft Edge Driver not found."
if edgedriver_upgrade_needed:
msg = "Microsoft Edge Driver update needed."
sys_args = sys.argv # Save a copy of current sys args
log_d("\n%s Getting it now:" % msg)
sb_install.main(override="edgedriver %s" % use_version)
sys.argv = sys_args # Put back the original sys args
else:
edgedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with edgedriver_fixing_lock:
msg = "Microsoft Edge Driver not found."
if edgedriver_upgrade_needed:
msg = "Microsoft Edge Driver update needed."
sys_args = sys.argv # Save a copy of current sys args
log_d("\n%s Getting it now:" % msg)
sb_install.main(override="edgedriver %s" % use_version)
sys.argv = sys_args # Put back the original sys args

# For Microsoft Edge (Chromium) version 80 or higher
Edge = webdriver.edge.webdriver.WebDriver
EdgeOptions = webdriver.edge.webdriver.Options
if LOCAL_EDGEDRIVER and os.path.exists(LOCAL_EDGEDRIVER):
try:
make_driver_executable_if_not(LOCAL_EDGEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make edgedriver"
" executable: %s" % e
)
edge_options = EdgeOptions()
edge_options.use_chromium = True
if locale_code:
prefs["intl.accept_languages"] = locale_code
if block_images:
prefs["profile.managed_default_content_settings.images"] = 2
if disable_js:
prefs["profile.managed_default_content_settings.javascript"] = 2
if do_not_track:
prefs["enable_do_not_track"] = True
if external_pdf:
prefs["plugins.always_open_pdf_externally"] = True
pdce = "user_experience_metrics.personalization_data_consent_enabled"
prefs[pdce] = True # Remove "Personalize your web experience" prompt
edge_options.add_experimental_option("prefs", prefs)
edge_options.add_argument(
"--disable-blink-features=AutomationControlled"
)
edge_options.add_experimental_option(
"excludeSwitches", ["enable-automation", "enable-logging"]
)
if log_cdp_events:
edge_options.set_capability(
"ms:loggingPrefs", {"performance": "ALL", "browser": "ALL"}
)
if host_resolver_rules:
edge_options.add_argument(
"--host-resolver-rules=%s" % host_resolver_rules
)
if not enable_sync:
edge_options.add_argument("--disable-sync")
if (
not recorder_ext and not disable_csp and not proxy_auth
):
edge_options.add_argument("--guest")
if dark_mode:
edge_options.add_argument("--enable-features=WebContentsForceDark")
if headless2:
try:
if use_version == "latest" or int(use_version) >= 109:
edge_options.add_argument("--headless=new")
else:
edge_options.add_argument("--headless=chrome")
except Exception:
edge_options.add_argument("--headless=new")
elif headless and undetectable:
# (For later: UC Mode doesn't support Edge now)
try:
if int(use_version) >= 109:
edge_options.add_argument("--headless=new")
elif (
int(use_version) >= 96
and int(use_version) <= 108
):
edge_options.add_argument("--headless=chrome")
else:
pass # Will need Xvfb on Linux
except Exception:
pass
elif headless:
if "--headless" not in edge_options.arguments:
edge_options.add_argument("--headless")
if mobile_emulator and not is_using_uc(undetectable, browser_name):
emulator_settings = {}
device_metrics = {}
if (
isinstance(device_width, int)
and isinstance(device_height, int)
and isinstance(device_pixel_ratio, (int, float))
):
device_metrics["width"] = device_width
device_metrics["height"] = device_height
device_metrics["pixelRatio"] = device_pixel_ratio
else:
device_metrics["width"] = constants.Mobile.WIDTH
device_metrics["height"] = constants.Mobile.HEIGHT
device_metrics["pixelRatio"] = constants.Mobile.RATIO
emulator_settings["deviceMetrics"] = device_metrics
if user_agent:
emulator_settings["userAgent"] = user_agent
edge_options.add_experimental_option(
"mobileEmulation", emulator_settings
)
if headless or headless2:
edge_options.add_argument(
"--window-size=%s,%s" % (
settings.HEADLESS_START_WIDTH,
settings.HEADLESS_START_HEIGHT,
)
)
else:
edge_options.add_argument(
"--window-size=%s,%s" % (
settings.CHROME_START_WIDTH,
settings.CHROME_START_HEIGHT,
)
)
if user_data_dir and not is_using_uc(undetectable, browser_name):
abs_path = os.path.abspath(user_data_dir)
edge_options.add_argument("--user-data-dir=%s" % abs_path)
if extension_zip:
# Can be a comma-separated list of .ZIP or .CRX files
extension_zip_list = extension_zip.split(",")
for extension_zip_item in extension_zip_list:
abs_path = os.path.abspath(extension_zip_item)
edge_options.add_extension(abs_path)
if extension_dir:
# load-extension input can be a comma-separated list
abs_path = os.path.abspath(extension_dir)
edge_options = add_chrome_ext_dir(edge_options, abs_path)
edge_options.add_argument("--disable-infobars")
edge_options.add_argument("--disable-notifications")
edge_options.add_argument("--disable-save-password-bubble")
edge_options.add_argument("--disable-single-click-autofill")
edge_options.add_argument(
"--disable-autofill-keyboard-accessory-view[8]"
)
edge_options.add_argument("--safebrowsing-disable-download-protection")
edge_options.add_argument("--disable-search-engine-choice-screen")
edge_options.add_argument("--disable-browser-side-navigation")
edge_options.add_argument("--disable-translate")
if not enable_ws:
edge_options.add_argument("--disable-web-security")
edge_options.add_argument("--homepage=about:blank")
edge_options.add_argument("--dns-prefetch-disable")
edge_options.add_argument("--dom-automation")
edge_options.add_argument("--disable-hang-monitor")
edge_options.add_argument("--disable-prompt-on-repost")
if not enable_3d_apis:
edge_options.add_argument("--disable-3d-apis")
if headless or headless2 or is_using_uc(undetectable, browser_name):
edge_options.add_argument("--disable-renderer-backgrounding")
edge_options.add_argument("--disable-backgrounding-occluded-windows")
edge_options.add_argument("--disable-client-side-phishing-detection")
edge_options.add_argument("--disable-oopr-debug-crash-dump")
edge_options.add_argument("--disable-top-sites")
edge_options.add_argument("--ash-no-nudges")
edge_options.add_argument("--no-crash-upload")
edge_options.add_argument("--deny-permission-prompts")
if (
page_load_strategy
and page_load_strategy.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
edge_options.page_load_strategy = page_load_strategy.lower()
elif (
not page_load_strategy
and hasattr(settings, "PAGE_LOAD_STRATEGY")
and settings.PAGE_LOAD_STRATEGY
and settings.PAGE_LOAD_STRATEGY.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
edge_options.page_load_strategy = (
settings.PAGE_LOAD_STRATEGY.lower()
)
if (settings.DISABLE_CSP_ON_CHROME or disable_csp) and not headless:
# Headless Edge doesn't support extensions, which are required
# for disabling the Content Security Policy on Edge
edge_options = _add_chrome_disable_csp_extension(edge_options)
if ad_block_on and not headless:
edge_options = _add_chrome_ad_block_extension(edge_options)
if recorder_ext and not headless:
edge_options = _add_chrome_recorder_extension(edge_options)
if proxy_string:
if proxy_auth:
edge_options = _add_chrome_proxy_extension(
edge_options,
proxy_string,
proxy_user,
proxy_pass,
proxy_bypass_list,
zip_it=True,
multi_proxy=multi_proxy,
)
edge_options.add_argument("--proxy-server=%s" % proxy_string)
if proxy_bypass_list:
edge_options.add_argument(
"--proxy-bypass-list=%s" % proxy_bypass_list
)
elif proxy_pac_url:
if proxy_auth:
edge_options = _add_chrome_proxy_extension(
edge_options,
None,
proxy_user,
proxy_pass,
proxy_bypass_list,
zip_it=True,
multi_proxy=multi_proxy,
)
edge_options.add_argument("--proxy-pac-url=%s" % proxy_pac_url)
edge_options.add_argument("--test-type")
edge_options.add_argument("--log-level=3")
edge_options.add_argument("--no-first-run")
edge_options.add_argument("--ignore-certificate-errors")
if devtools and not headless:
edge_options.add_argument("--auto-open-devtools-for-tabs")
edge_options.add_argument("--allow-file-access-from-files")
edge_options.add_argument("--allow-insecure-localhost")
edge_options.add_argument("--allow-running-insecure-content")
if user_agent:
edge_options.add_argument("--user-agent=%s" % user_agent)
if (
IS_LINUX
or (IS_MAC and not is_using_uc(undetectable, browser_name))
):
edge_options.add_argument("--no-sandbox")
if remote_debug:
# To access the Debugger, go to: edge://inspect/#devices
# while a Chromium driver is running.
# Info: https://chromedevtools.github.io/devtools-protocol/
args = " ".join(sys.argv)
free_port = 9222
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
free_port = service_utils.free_port()
edge_options.add_argument("--remote-debugging-port=%s" % free_port)
if swiftshader:
edge_options.add_argument("--use-gl=angle")
edge_options.add_argument("--use-angle=swiftshader-webgl")
elif (
not is_using_uc(undetectable, browser_name)
and not enable_3d_apis
):
edge_options.add_argument("--disable-gpu")
if IS_LINUX:
edge_options.add_argument("--disable-dev-shm-usage")
extra_disabled_features = []
set_binary = False
if chromium_arg:
# Can be a comma-separated list of Chromium args
chromium_arg_list = chromium_arg.split(",")
for chromium_arg_item in chromium_arg_list:
chromium_arg_item = chromium_arg_item.strip()
if not chromium_arg_item.startswith("--"):
if chromium_arg_item.startswith("-"):
chromium_arg_item = "-" + chromium_arg_item
else:
chromium_arg_item = "--" + chromium_arg_item
if "set-binary" in chromium_arg_item:
set_binary = True
elif "disable-features=" in chromium_arg_item:
d_f = chromium_arg_item.split("disable-features=")[-1]
extra_disabled_features.append(d_f)
elif len(chromium_arg_item) >= 3:
edge_options.add_argument(chromium_arg_item)
if disable_features:
extra_disabled_features.extend(disable_features.split(","))
edge_options.add_argument(
'--simulate-outdated-no-au="Tue, 31 Dec 2099 23:59:59 GMT"'
)
edge_options.add_argument("--disable-ipc-flooding-protection")
edge_options.add_argument("--disable-password-generation")
edge_options.add_argument("--disable-domain-reliability")
edge_options.add_argument("--disable-component-update")
edge_options.add_argument("--disable-breakpad")
included_disabled_features = []
included_disabled_features.append("OptimizationHints")
included_disabled_features.append("OptimizationHintsFetching")
included_disabled_features.append("Translate")
included_disabled_features.append("OptimizationTargetPrediction")
included_disabled_features.append("OptimizationGuideModelDownloading")
included_disabled_features.append("InsecureDownloadWarnings")
included_disabled_features.append("InterestFeedContentSuggestions")
included_disabled_features.append("PrivacySandboxSettings4")
included_disabled_features.append("SidePanelPinning")
included_disabled_features.append("UserAgentClientHint")
for item in extra_disabled_features:
if item not in included_disabled_features:
included_disabled_features.append(item)
d_f_string = ",".join(included_disabled_features)
edge_options.add_argument("--disable-features=%s" % d_f_string)
if (set_binary or IS_LINUX) and not binary_location:
br_app = "edge"
binary_loc = detect_b_ver.get_binary_location(br_app)
if os.path.exists(binary_loc):
binary_location = binary_loc
if binary_location:
edge_options.binary_location = binary_location
service = EdgeService(
executable_path=LOCAL_EDGEDRIVER,
log_output=os.devnull,
service_args=["--disable-build-check"],
)
try:
driver = Edge(service=service, options=edge_options)
except Exception as e:
if not hasattr(e, "msg"):
raise
auto_upgrade_edgedriver = False
edge_version = None
if (
"This version of MSEdgeDriver only supports" in e.msg
or "This version of Microsoft Edge WebDriver" in e.msg
):
if "Current browser version is " in e.msg:
auto_upgrade_edgedriver = True
edge_version = e.msg.split(
"Current browser version is "
)[1].split(" ")[0]
elif "only supports MSEdge version " in e.msg:
auto_upgrade_edgedriver = True
edge_version = e.msg.split(
"only supports MSEdge version "
)[1].split(" ")[0]
elif "DevToolsActivePort file doesn't exist" in e.msg:
# https://stackoverflow.com/a/56638103/7058266
args = " ".join(sys.argv)
free_port = 9222
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
free_port = service_utils.free_port()
edge_options.add_argument(
"--remote-debugging-port=%s" % free_port
)
driver = Edge(service=service, options=edge_options)
return extend_driver(driver)
if not auto_upgrade_edgedriver:
raise # Not an obvious fix.
else:
pass # Try upgrading EdgeDriver to match Edge.
args = " ".join(sys.argv)
if "-n" in sys.argv or " -n=" in args or args == "-c":
edgedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with edgedriver_fixing_lock:
try:
if not _was_driver_repaired():
_repair_edgedriver(edge_version)
_mark_driver_repaired()
except Exception:
pass
else:
try:
if not _was_driver_repaired():
_repair_edgedriver(edge_version)
_mark_driver_repaired()
except Exception:
pass
driver = Edge(service=service, options=edge_options)
return extend_driver(driver)
elif browser_name == constants.Browser.SAFARI:
args = " ".join(sys.argv)
if ("-n" in sys.argv or " -n=" in args or args == "-c"):
# Skip if multithreaded
raise Exception("Can't run Safari tests in multithreaded mode!")
warnings.simplefilter("ignore", category=DeprecationWarning)
from selenium.webdriver.safari.options import Options as SafariOptions
service = SafariService(quiet=False)
options = SafariOptions()
if (
page_load_strategy
and page_load_strategy.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
options.page_load_strategy = page_load_strategy.lower()
elif (
not page_load_strategy
and hasattr(settings, "PAGE_LOAD_STRATEGY")
and settings.PAGE_LOAD_STRATEGY
and settings.PAGE_LOAD_STRATEGY.lower() in ["eager", "none"]
):
# Only change it if not "normal", which is the default.
options.page_load_strategy = settings.PAGE_LOAD_STRATEGY.lower()
driver = webdriver.safari.webdriver.WebDriver(
service=service, options=options
)
return extend_driver(driver)
elif browser_name == constants.Browser.GOOGLE_CHROME:
try:
chrome_options = _set_chrome_options(
browser_name,
downloads_path,
headless,
locale_code,
proxy_string,
proxy_auth,
proxy_user,
proxy_pass,
proxy_bypass_list,
proxy_pac_url,
multi_proxy,
user_agent,
recorder_ext,
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
undetectable,
uc_cdp_events,
uc_subprocess,
log_cdp_events,
no_sandbox,
disable_gpu,
headless2,
incognito,
guest_mode,
dark_mode,
devtools,
remote_debug,
enable_3d_apis,
swiftshader,
ad_block_on,
host_resolver_rules,
block_images,
do_not_track,
chromium_arg,
user_data_dir,
extension_zip,
extension_dir,
disable_features,
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
servername,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
use_version = "latest"
major_chrome_version = None
saved_mcv = None
full_ch_version = None
full_ch_driver_version = None
use_br_version_for_uc = False
try:
if chrome_options.binary_location:
try:
major_chrome_version = (
detect_b_ver.get_browser_version_from_binary(
chrome_options.binary_location,
)
)
saved_mcv = major_chrome_version
major_chrome_version = saved_mcv.split(".")[0]
if len(major_chrome_version) < 2:
major_chrome_version = None
except Exception:
major_chrome_version = None
if not major_chrome_version:
br_app = "google-chrome"
full_ch_version = (
detect_b_ver.get_browser_version_from_os(br_app)
)
saved_mcv = full_ch_version
major_chrome_version = full_ch_version.split(".")[0]
if int(major_chrome_version) < 67:
major_chrome_version = None
elif (
int(major_chrome_version) >= 67
and int(major_chrome_version) <= 72
):
# chromedrivers 2.41 - 2.46 could be swapped with 72
major_chrome_version = "72"
elif int(major_chrome_version) >= 115:
if (
driver_version == "browser"
and saved_mcv
and len(saved_mcv.split(".")) == 4
):
driver_version = saved_mcv
if is_using_uc(undetectable, browser_name):
use_br_version_for_uc = True
if (
(headless or headless2)
and IS_WINDOWS
and major_chrome_version
and int(major_chrome_version) >= 117
and not is_using_uc(undetectable, browser_name)
and not (remote_debug or devtools or use_wire)
and not (proxy_string or multi_proxy or proxy_pac_url)
and (not chromium_arg or "debug" not in chromium_arg)
and (not servername or servername == "localhost")
):
# Hide the "DevTools listening on ..." message.
# https://bugs.chromium.org
# /p/chromedriver/issues/detail?id=4403#c35
# (Only when the remote debugging port is not needed.)
chrome_options.add_argument("--remote-debugging-pipe")
except Exception:
major_chrome_version = None
if major_chrome_version:
use_version = major_chrome_version
ch_driver_version = None
path_chromedriver = chromedriver_on_path()
if os.path.exists(LOCAL_CHROMEDRIVER):
try:
output = subprocess.check_output(
'"%s" --version' % LOCAL_CHROMEDRIVER, shell=True
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
full_ch_driver_version = output.split(" ")[1]
output = full_ch_driver_version.split(".")[0]
if int(output) >= 2:
ch_driver_version = output
if driver_version == "keep":
driver_version = ch_driver_version
except Exception:
pass
elif path_chromedriver:
try:
make_driver_executable_if_not(path_chromedriver)
except Exception as e:
logging.debug(
"\nWarning: Could not make chromedriver"
" executable: %s" % e
)
try:
output = subprocess.check_output(
'"%s" --version' % path_chromedriver, shell=True
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
full_ch_driver_version = output.split(" ")[1]
output = full_ch_driver_version.split(".")[0]
if int(output) >= 2:
ch_driver_version = output
if driver_version == "keep":
use_version = ch_driver_version
except Exception:
pass
disable_build_check = True
uc_driver_version = None
if is_using_uc(undetectable, browser_name):
if use_br_version_for_uc or driver_version == "mlatest":
uc_driver_version = get_uc_driver_version(full=True)
full_ch_driver_version = uc_driver_version
else:
uc_driver_version = get_uc_driver_version()
if multi_proxy:
sb_config.multi_proxy = True
if uc_driver_version and driver_version == "keep":
driver_version = uc_driver_version
use_version = find_chromedriver_version_to_use(
use_version, driver_version
)
if headless2:
try:
if (
use_version == "latest"
or int(str(use_version).split(".")[0]) >= 109
):
chrome_options.add_argument("--headless=new")
else:
chrome_options.add_argument("--headless=chrome")
except Exception:
chrome_options.add_argument("--headless=new")
elif headless and undetectable:
try:
int_use_version = int(str(use_version).split(".")[0])
if int_use_version >= 109:
chrome_options.add_argument("--headless=new")
elif (
int_use_version >= 96
and int_use_version <= 108
):
chrome_options.add_argument("--headless=chrome")
else:
pass # Will need Xvfb on Linux
except Exception:
pass # Will need Xvfb on Linux
elif headless:
if "--headless" not in chrome_options.arguments:
chrome_options.add_argument("--headless")
if LOCAL_CHROMEDRIVER and os.path.exists(LOCAL_CHROMEDRIVER):
try:
make_driver_executable_if_not(LOCAL_CHROMEDRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make chromedriver"
" executable: %s" % e
)
use_uc = is_using_uc(undetectable, browser_name)
make_uc_driver_from_chromedriver = False
local_ch_exists = (
LOCAL_CHROMEDRIVER and os.path.exists(LOCAL_CHROMEDRIVER)
)
"""If no LOCAL_CHROMEDRIVER, but path_chromedriver, and the
browser version nearly matches the driver version, then use
the path_chromedriver instead of downloading a new driver.
Eg. 116.0.* for both is close, but not 116.0.* and 116.1.*"""
browser_driver_close_match = False
if (
path_chromedriver
and full_ch_version
and full_ch_driver_version
):
full_ch_v_p = full_ch_version.split(".")[0:2]
full_ch_driver_v_p = full_ch_driver_version.split(".")[0:2]
if (
full_ch_v_p == full_ch_driver_v_p
or driver_version == "keep"
):
browser_driver_close_match = True
# If not ARM MAC and need to use uc_driver (and it's missing),
# and already have chromedriver with the correct version,
# then copy chromedriver to uc_driver (and it'll get patched).
if (
not IS_ARM_MAC
and use_uc
and (
(
(local_ch_exists or path_chromedriver)
and use_version == ch_driver_version
and (
not os.path.exists(LOCAL_UC_DRIVER)
or uc_driver_version != use_version
)
)
or (
local_ch_exists
and use_version == "latest"
and not os.path.exists(LOCAL_UC_DRIVER)
)
)
):
make_uc_driver_from_chromedriver = True
elif (
(use_uc and not os.path.exists(LOCAL_UC_DRIVER))
or (not use_uc and not path_chromedriver)
or (
not use_uc
and use_version != "latest" # Browser version detected
and (ch_driver_version or not local_ch_exists)
and (
use_version.split(".")[0] != ch_driver_version
or (
not local_ch_exists
and use_version.isnumeric()
and int(use_version) >= 115
and not browser_driver_close_match
)
)
)
or (
use_uc
and use_version != "latest" # Browser version detected
and uc_driver_version != use_version
)
or (
full_ch_driver_version # Also used for the uc_driver
and driver_version
and len(str(driver_version).split(".")) == 4
and full_ch_driver_version != driver_version
)
):
# chromedriver download needed in the seleniumbase/drivers dir
from seleniumbase.console_scripts import sb_install
args = " ".join(sys.argv)
if not ("-n" in sys.argv or " -n=" in args or args == "-c"):
# (Not multithreaded)
sys_args = sys.argv # Save a copy of current sys args
msg = "chromedriver update needed. Getting it now:"
if not path_chromedriver:
msg = "chromedriver not found. Getting it now:"
if use_uc and not os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver not found. Getting it now:"
if use_uc and os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver update needed. Getting it now:"
log_d("\nWarning: %s" % msg)
force_uc = False
intel_for_uc = False
if use_uc:
force_uc = True
if IS_ARM_MAC and use_uc:
intel_for_uc = True # Use Intel's driver for UC Mode
try:
sb_install.main(
override="chromedriver %s" % use_version,
intel_for_uc=intel_for_uc,
force_uc=force_uc,
)
except Exception:
d_latest = get_latest_chromedriver_version()
if (
d_latest
and use_version != "latest"
and int(use_version) > int(d_latest.split(".")[0])
):
disable_build_check = True
d_latest_major = d_latest.split(".")[0]
if (
not path_chromedriver
or (
ch_driver_version
and (
int(ch_driver_version)
< int(d_latest_major)
)
)
):
sb_install.main(override="chromedriver latest")
sys.argv = sys_args # Put back the original sys args
else:
# (Multithreaded)
chromedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with chromedriver_fixing_lock:
msg = "chromedriver update needed. Getting it now:"
if not path_chromedriver:
msg = "chromedriver not found. Getting it now:"
if use_uc and not os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver not found. Getting it now:"
if use_uc and os.path.exists(LOCAL_UC_DRIVER):
msg = "uc_driver update needed. Getting it now:"
force_uc = False
intel_for_uc = False
if use_uc:
force_uc = True
if IS_ARM_MAC and use_uc:
intel_for_uc = True # Use Intel driver for UC Mode
if os.path.exists(LOCAL_CHROMEDRIVER):
try:
output = subprocess.check_output(
'"%s" --version' % LOCAL_CHROMEDRIVER,
shell=True,
)
if IS_WINDOWS:
output = output.decode("latin1")
else:
output = output.decode("utf-8")
full_ch_driver_version = output.split(" ")[1]
output = full_ch_driver_version.split(".")[0]
if int(output) >= 2:
ch_driver_version = output
except Exception:
pass
if (
(
not use_uc
and not os.path.exists(LOCAL_CHROMEDRIVER)
)
or (use_uc and not os.path.exists(LOCAL_UC_DRIVER))
or (
not use_uc
and (
use_version.split(".")[0]
!= ch_driver_version
)
)
or (
use_uc
and (
use_version.split(".")[0]
!= get_uc_driver_version()
)
)
):
log_d("\nWarning: %s" % msg)
sys_args = sys.argv # Save a copy of sys args
try:
sb_install.main(
override="chromedriver %s" % use_version,
intel_for_uc=intel_for_uc,
force_uc=force_uc,
)
except Exception:
d_latest = get_latest_chromedriver_version()
if (
d_latest
and use_version != "latest"
and (
int(use_version)
> int(d_latest.split(".")[0])
)
):
disable_build_check = True
d_latest_major = d_latest.split(".")[0]
if (
not path_chromedriver
or (
ch_driver_version
and (
int(ch_driver_version)
< int(d_latest_major)
)
)
):
sb_install.main(
override="chromedriver latest"
)
finally:
sys.argv = sys_args # Put back original args
service_args = []
if disable_build_check:
service_args = ["--disable-build-check"]
if is_using_uc(undetectable, browser_name):
uc_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with uc_lock: # Avoid multithreaded issues
if make_uc_driver_from_chromedriver:
if os.path.exists(LOCAL_CHROMEDRIVER):
shutil.copyfile(
LOCAL_CHROMEDRIVER, LOCAL_UC_DRIVER
)
elif os.path.exists(path_chromedriver):
shutil.copyfile(
path_chromedriver, LOCAL_UC_DRIVER
)
try:
make_driver_executable_if_not(LOCAL_UC_DRIVER)
except Exception as e:
logging.debug(
"\nWarning: Could not make uc_driver"
" executable: %s" % e
)
if (
not headless
or not IS_LINUX
or is_using_uc(undetectable, browser_name)
):
uc_activated = False
try:
if (
os.path.exists(LOCAL_CHROMEDRIVER)
or is_using_uc(undetectable, browser_name)
):
if headless and not IS_LINUX:
undetectable = False # No support for headless
if is_using_uc(undetectable, browser_name):
from seleniumbase import undetected
from urllib.error import URLError
if IS_LINUX:
if "--headless" in (
chrome_options.arguments
):
chrome_options.arguments.remove(
"--headless"
)
uc_chrome_version = None
if (
use_version.isnumeric()
and int(use_version) >= 72
):
uc_chrome_version = int(use_version)
elif (
str(use_version).split(".")[0].isnumeric()
and int(str(use_version).split(".")[0]) >= 72
):
uc_chrome_version = (
int(str(use_version).split(".")[0])
)
cdp_events = uc_cdp_events
cert = "unable to get local issuer certificate"
mac_certificate_error = False
if (
use_version.isnumeric()
and int(use_version) <= 74
):
chrome_options.add_experimental_option(
"w3c", True
)
if (
(not user_agent or "Headless" in user_agent)
and uc_chrome_version
and uc_chrome_version >= 117
and (headless or headless2)
and hasattr(sb_config, "uc_agent_cache")
):
user_agent = sb_config.uc_agent_cache
chrome_options.add_argument(
"--user-agent=%s" % user_agent
)
try:
if (
(
not user_agent
or "Headless" in user_agent
)
and uc_chrome_version
and uc_chrome_version >= 117
and (headless or headless2)
):
from seleniumbase.console_scripts import (
sb_install
)
sb_config.uc_user_agent_cache = True
headless_options = _set_chrome_options(
browser_name,
downloads_path,
True, # headless
locale_code,
None, # proxy_string
None, # proxy_auth
None, # proxy_user
None, # proxy_pass
None, # proxy_bypass_list
None, # proxy_pac_url
None, # multi_proxy
None, # user_agent
None, # recorder_ext
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
False, # undetectable
False, # uc_cdp_events
False, # uc_subprocess
False, # log_cdp_events
no_sandbox,
disable_gpu,
False, # headless2
incognito,
guest_mode,
dark_mode,
None, # devtools
remote_debug,
enable_3d_apis,
swiftshader,
None, # ad_block_on
None, # host_resolver_rules
block_images,
do_not_track,
None, # chromium_arg
None, # user_data_dir
None, # extension_zip
None, # extension_dir
None, # disable_features
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
servername,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
if (
not path_chromedriver
or (
ch_driver_version
and use_version
and (
int(ch_driver_version)
< int(str(
use_version).split(".")[0]
)
)
)
):
sb_install.main(
override="chromedriver %s"
% use_version,
intel_for_uc=False,
force_uc=False,
)
d_b_c = "--disable-build-check"
if os.path.exists(LOCAL_CHROMEDRIVER):
service = ChromeService(
executable_path=LOCAL_CHROMEDRIVER,
log_output=os.devnull,
service_args=[d_b_c],
)
driver = webdriver.Chrome(
service=service,
options=headless_options,
)
else:
service = ChromeService(
log_output=os.devnull,
service_args=[d_b_c],
)
driver = webdriver.Chrome(
service=service,
options=headless_options,
)
try:
user_agent = driver.execute_script(
"return navigator.userAgent;"
)
if (
major_chrome_version
and full_ch_version
and full_ch_version.count(".") == 3
and full_ch_version in user_agent
):
mcv = major_chrome_version
user_agent = user_agent.replace(
"Chrome/%s" % full_ch_version,
"Chrome/%s.0.0.0" % mcv
)
user_agent = user_agent.replace(
"Headless", ""
)
chrome_options.add_argument(
"--user-agent=%s" % user_agent
)
sb_config.uc_agent_cache = user_agent
except Exception:
pass
driver.quit()
except Exception:
pass
uc_path = None
if os.path.exists(LOCAL_UC_DRIVER):
uc_path = LOCAL_UC_DRIVER
uc_path = os.path.realpath(uc_path)
try:
driver = undetected.Chrome(
options=chrome_options,
user_data_dir=user_data_dir,
driver_executable_path=uc_path,
browser_executable_path=b_path,
enable_cdp_events=cdp_events,
headless=False, # Xvfb needed!
version_main=uc_chrome_version,
use_subprocess=True, # Always!
)
uc_activated = True
except URLError as e:
if cert in e.args[0] and IS_MAC:
mac_certificate_error = True
else:
raise
except SessionNotCreatedException:
time.sleep(0.2)
driver = undetected.Chrome(
options=chrome_options,
user_data_dir=user_data_dir,
driver_executable_path=uc_path,
browser_executable_path=b_path,
enable_cdp_events=cdp_events,
headless=False, # Xvfb needed!
version_main=uc_chrome_version,
use_subprocess=True, # Always!
)
uc_activated = True
if mac_certificate_error:
cf_lock_path = (
constants.MultiBrowser.CERT_FIXING_LOCK
)
cf_lock = fasteners.InterProcessLock(
constants.MultiBrowser.CERT_FIXING_LOCK
)
if not os.path.exists(cf_lock_path):
# Avoid multithreaded issues
with cf_lock:
# Install Python Certificates (MAC)
os.system(
r"bash /Applications/Python*/"
r"Install\ "
r"Certificates.command"
)
driver = undetected.Chrome(
options=chrome_options,
user_data_dir=user_data_dir,
driver_executable_path=uc_path,
browser_executable_path=b_path,
enable_cdp_events=cdp_events,
headless=False, # Xvfb needed!
version_main=uc_chrome_version,
use_subprocess=True, # Always!
)
uc_activated = True
else:
if (
use_version.isnumeric()
and int(use_version) <= 74
):
chrome_options.add_experimental_option(
"w3c", True
)
service = ChromeService(
executable_path=LOCAL_CHROMEDRIVER,
log_output=os.devnull,
service_args=service_args,
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
else:
service = ChromeService(
log_output=os.devnull,
service_args=service_args,
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
except Exception as e:
if not hasattr(e, "msg"):
raise
auto_upgrade_chromedriver = False
if "This version of ChromeDriver only supports" in e.msg:
auto_upgrade_chromedriver = True
elif "Chrome version must be between" in e.msg:
auto_upgrade_chromedriver = True
elif "Missing or invalid capabilities" in e.msg:
chrome_options.add_experimental_option("w3c", True)
service = ChromeService(
log_output=os.devnull,
service_args=service_args,
)
with warnings.catch_warnings():
warnings.simplefilter(
"ignore", category=DeprecationWarning
)
driver = webdriver.Chrome(
service=service, options=chrome_options
)
return extend_driver(driver)
if not auto_upgrade_chromedriver:
raise # Not an obvious fix.
else:
pass # Try upgrading ChromeDriver to match Chrome.
mcv = None # Major Chrome Version
if "Current browser version is " in e.msg:
line = e.msg.split("Current browser version is ")[1]
browser_version = line.split(" ")[0]
major_chrome_version = browser_version.split(".")[0]
if (
major_chrome_version.isnumeric()
and int(major_chrome_version) >= 86
):
mcv = major_chrome_version
mcv = find_chromedriver_version_to_use(
mcv, driver_version
)
headless_options = _set_chrome_options(
browser_name,
downloads_path,
True, # headless
locale_code,
None, # proxy_string
None, # proxy_auth
None, # proxy_user
None, # proxy_pass
None, # proxy_bypass_list
None, # proxy_pac_url
None, # multi_proxy
None, # user_agent
None, # recorder_ext
disable_js,
disable_csp,
enable_ws,
enable_sync,
use_auto_ext,
False, # undetectable
False, # uc_cdp_events
False, # uc_subprocess
False, # log_cdp_events
no_sandbox,
disable_gpu,
False, # headless2
incognito,
guest_mode,
dark_mode,
None, # devtools
remote_debug,
enable_3d_apis,
swiftshader,
None, # ad_block_on
None, # host_resolver_rules
block_images,
do_not_track,
None, # chromium_arg
None, # user_data_dir
None, # extension_zip
None, # extension_dir
None, # disable_features
binary_location,
driver_version,
page_load_strategy,
use_wire,
external_pdf,
servername,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
args = " ".join(sys.argv)
if "-n" in sys.argv or " -n=" in args or args == "-c":
chromedriver_fixing_lock = fasteners.InterProcessLock(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with chromedriver_fixing_lock:
if not _was_driver_repaired():
_repair_chromedriver(
chrome_options, headless_options, mcv
)
_mark_driver_repaired()
else:
if not _was_driver_repaired():
_repair_chromedriver(
chrome_options, headless_options, mcv
)
_mark_driver_repaired()
if os.path.exists(LOCAL_CHROMEDRIVER):
service = ChromeService(
executable_path=LOCAL_CHROMEDRIVER,
log_output=os.devnull,
service_args=["--disable-build-check"],
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
else:
service = ChromeService(
log_output=os.devnull,
service_args=["--disable-build-check"],
)
driver = webdriver.Chrome(
service=service,
options=chrome_options,
)
driver.default_get = driver.get # Save copy of original
if uc_activated:
driver.get = lambda url: uc_special_open_if_cf(
driver,
url,
proxy_string,
mobile_emulator,
device_width,
device_height,
device_pixel_ratio,
)
driver.uc_open = lambda url: uc_open(driver, url)
driver.uc_open_with_tab = (
lambda url: uc_open_with_tab(driver, url)
)
driver.uc_open_with_reconnect = (
lambda *args, **kwargs: uc_open_with_reconnect(
driver, *args, **kwargs
)
)
driver.uc_open_with_disconnect = (
lambda *args, **kwargs: uc_open_with_disconnect(
driver, *args, **kwargs
)
)
driver.uc_click = lambda *args, **kwargs: uc_click(
driver, *args, **kwargs
)
driver.uc_gui_press_key = (
lambda *args, **kwargs: uc_gui_press_key(
driver, *args, **kwargs
)
)
driver.uc_gui_press_keys = (
lambda *args, **kwargs: uc_gui_press_keys(
driver, *args, **kwargs
)
)
driver.uc_gui_write = (
lambda *args, **kwargs: uc_gui_write(
driver, *args, **kwargs
)
)
driver.uc_gui_click_x_y = (
lambda *args, **kwargs: uc_gui_click_x_y(
driver, *args, **kwargs
)
)
driver.uc_gui_click_captcha = (
lambda *args, **kwargs: uc_gui_click_captcha(
driver, *args, **kwargs
)
)
driver.uc_gui_click_cf = (
lambda *args, **kwargs: uc_gui_click_cf(
driver, *args, **kwargs
)
)
driver.uc_gui_click_rc = (
lambda *args, **kwargs: uc_gui_click_rc(
driver, *args, **kwargs
)
)
driver.uc_gui_handle_captcha = (
lambda *args, **kwargs: uc_gui_handle_captcha(
driver, *args, **kwargs
)
)
driver.uc_gui_handle_cf = (
lambda *args, **kwargs: uc_gui_handle_cf(
driver, *args, **kwargs
)
)
driver.uc_gui_handle_rc = (
lambda *args, **kwargs: uc_gui_handle_rc(
driver, *args, **kwargs
)
)
driver.uc_switch_to_frame = (
lambda *args, **kwargs: uc_switch_to_frame(
driver, *args, **kwargs
)
)
driver._is_hidden = (headless or headless2)
driver._is_using_uc = True
if mobile_emulator:
uc_metrics = {}
if (
isinstance(device_width, int)
and isinstance(device_height, int)
and isinstance(device_pixel_ratio, (int, float))
):
uc_metrics["width"] = device_width
uc_metrics["height"] = device_height
uc_metrics["pixelRatio"] = device_pixel_ratio
else:
uc_metrics["width"] = constants.Mobile.WIDTH
uc_metrics["height"] = constants.Mobile.HEIGHT
uc_metrics["pixelRatio"] = constants.Mobile.RATIO
set_device_metrics_override = dict(
{
"width": uc_metrics["width"],
"height": uc_metrics["height"],
"deviceScaleFactor": uc_metrics["pixelRatio"],
"mobile": True
}
)
try:
driver.execute_cdp_cmd(
'Emulation.setDeviceMetricsOverride',
set_device_metrics_override
)
except Exception:
pass
return extend_driver(driver)
else: # Running headless on Linux (and not using --uc)
try:
> driver = webdriver.Chrome(options=chrome_options)

/usr/local/lib/python3.10/dist-packages/seleniumbase/core/browser_launcher.py:4613:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chrome/webdriver.py:45: in __init__
super().__init__(
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chromium/webdriver.py:50: in __init__
if finder.get_browser_path():
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:47: in get_browser_path
return self._binary_paths()["browser_path"]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f523ea6890>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
output = SeleniumManager().binary_paths(self._to_args())
if Path(output["driver_path"]).is_file():
self._paths["driver_path"] = output["driver_path"]
else:
raise ValueError(f'The driver path is not a valid file: {output["driver_path"]}')
if Path(output["browser_path"]).is_file():
self._paths["browser_path"] = output["browser_path"]
else:
raise ValueError(f'The browser path is not a valid file: {output["browser_path"]}')
except Exception as err:
msg = f"Unable to obtain driver for {browser}"
> raise NoSuchDriverException(msg) from err
E selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for chrome; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:78: NoSuchDriverException

During handling of the above exception, another exception occurred:

args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
> completed_proc = subprocess.run(args, capture_output=True)

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:116:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.10/subprocess.py:503: in run
with Popen(*popenargs, **kwargs) as process:
/usr/lib/python3.10/subprocess.py:971: in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <Popen: returncode: None args: ['/usr/local/lib/python3.10/dist-packages/sel...>
args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]
executable = b'/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager'
preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None
startupinfo = None, creationflags = 0, shell = False, p2cread = -1
p2cwrite = -1, c2pread = 15, c2pwrite = 18, errread = 19, errwrite = 20
restore_signals = True, gid = None, gids = None, uid = None, umask = -1
start_new_session = False

def _execute_child(self, args, executable, preexec_fn, close_fds,
pass_fds, cwd, env,
startupinfo, creationflags, shell,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite,
restore_signals,
gid, gids, uid, umask,
start_new_session):
"""Execute program (POSIX version)"""

if isinstance(args, (str, bytes)):
args = [args]
elif isinstance(args, os.PathLike):
if shell:
raise TypeError('path-like args is not allowed when '
'shell is true')
args = [args]
else:
args = list(args)

if shell:
# On Android the default shell is at '/system/bin/sh'.
unix_shell = ('/system/bin/sh' if
hasattr(sys, 'getandroidapilevel') else '/bin/sh')
args = [unix_shell, "-c"] + args
if executable:
args[0] = executable

if executable is None:
executable = args[0]

sys.audit("subprocess.Popen", executable, args, cwd, env)

if (_USE_POSIX_SPAWN
and os.path.dirname(executable)
and preexec_fn is None
and not close_fds
and not pass_fds
and cwd is None
and (p2cread == -1 or p2cread > 2)
and (c2pwrite == -1 or c2pwrite > 2)
and (errwrite == -1 or errwrite > 2)
and not start_new_session
and gid is None
and gids is None
and uid is None
and umask < 0):
self._posix_spawn(args, executable, env, restore_signals,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite)
return

orig_executable = executable

# For transferring possible exec failure from child to parent.
# Data format: "exception name:hex errno:description"
# Pickle is not used; it is complex and involves memory allocation.
errpipe_read, errpipe_write = os.pipe()
# errpipe_write must not be in the standard io 0, 1, or 2 fd range.
low_fds_to_close = []
while errpipe_write < 3:
low_fds_to_close.append(errpipe_write)
errpipe_write = os.dup(errpipe_write)
for low_fd in low_fds_to_close:
os.close(low_fd)
try:
try:
# We must avoid complex work that could involve
# malloc or free in the child process to avoid
# potential deadlocks, thus we do all this here.
# and pass it to fork_exec()

if env is not None:
env_list = []
for k, v in env.items():
k = os.fsencode(k)
if b'=' in k:
raise ValueError("illegal environment variable name")
env_list.append(k + b'=' + os.fsencode(v))
else:
env_list = None # Use execv instead of execve.
executable = os.fsencode(executable)
if os.path.dirname(executable):
executable_list = (executable,)
else:
# This matches the behavior of os._execvpe().
executable_list = tuple(
os.path.join(os.fsencode(dir), executable)
for dir in os.get_exec_path(env))
fds_to_keep = set(pass_fds)
fds_to_keep.add(errpipe_write)
> self.pid = _posixsubprocess.fork_exec(
args, executable_list,
close_fds, tuple(sorted(map(int, fds_to_keep))),
cwd, env_list,
p2cread, p2cwrite, c2pread, c2pwrite,
errread, errwrite,
errpipe_read, errpipe_write,
restore_signals, start_new_session,
gid, gids, uid, umask,
preexec_fn)
E BlockingIOError: [Errno 11] Resource temporarily unavailable

/usr/lib/python3.10/subprocess.py:1796: BlockingIOError

The above exception was the direct cause of the following exception:

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f523ea6800>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
> output = SeleniumManager().binary_paths(self._to_args())

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:67:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:54: in binary_paths
return self._run(args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

args = ['/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager', '--browser', 'chrome', '--language-binding', 'python', '--output', ...]

@staticmethod
def _run(args: List[str]) -> dict:
"""Executes the Selenium Manager Binary.

:Args:
- args: the components of the command being executed.
:Returns: The log string containing the driver location.
"""
command = " ".join(args)
logger.debug("Executing process: %s", command)
try:
if sys.platform == "win32":
completed_proc = subprocess.run(args, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
completed_proc = subprocess.run(args, capture_output=True)
stdout = completed_proc.stdout.decode("utf-8").rstrip("\n")
stderr = completed_proc.stderr.decode("utf-8").rstrip("\n")
output = json.loads(stdout) if stdout != "" else {"logs": [], "result": {}}
except Exception as err:
> raise WebDriverException(f"Unsuccessful command executed: {command}") from err
E selenium.common.exceptions.WebDriverException: Message: Unsuccessful command executed: /usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/linux/selenium-manager --browser chrome --language-binding python --output json

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/selenium_manager.py:121: WebDriverException

The above exception was the direct cause of the following exception:
/usr/local/lib/python3.10/dist-packages/seleniumbase/fixtures/base_case.py:14917: in setUp
self.driver = self.get_new_driver(
/usr/local/lib/python3.10/dist-packages/seleniumbase/fixtures/base_case.py:4101: in get_new_driver
new_driver = browser_launcher.get_driver(
/usr/local/lib/python3.10/dist-packages/seleniumbase/core/browser_launcher.py:2339: in get_driver
return get_local_driver(
/usr/local/lib/python3.10/dist-packages/seleniumbase/core/browser_launcher.py:4695: in get_local_driver
driver = webdriver.Chrome(
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chrome/webdriver.py:45: in __init__
super().__init__(
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/chromium/webdriver.py:50: in __init__
if finder.get_browser_path():
/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:47: in get_browser_path
return self._binary_paths()["browser_path"]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.common.driver_finder.DriverFinder object at 0x74f523ea6800>

def _binary_paths(self) -> dict:
if self._paths["driver_path"]:
return self._paths

browser = self._options.capabilities["browserName"]
try:
path = self._service.path
if path:
logger.debug(
"Skipping Selenium Manager; path to %s driver specified in Service class: %s", browser, path
)
if not Path(path).is_file():
raise ValueError(f"The path is not a valid file: {path}")
self._paths["driver_path"] = path
else:
output = SeleniumManager().binary_paths(self._to_args())
if Path(output["driver_path"]).is_file():
self._paths["driver_path"] = output["driver_path"]
else:
raise ValueError(f'The driver path is not a valid file: {output["driver_path"]}')
if Path(output["browser_path"]).is_file():
self._paths["browser_path"] = output["browser_path"]
else:
raise ValueError(f'The browser path is not a valid file: {output["browser_path"]}')
except Exception as err:
msg = f"Unable to obtain driver for {browser}"
> raise NoSuchDriverException(msg) from err
E selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for chrome; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location

/usr/local/lib/python3.10/dist-packages/selenium/webdriver/common/driver_finder.py:78: NoSuchDriverException