Skip to content

Commit 7464c4a

Browse files
authored
Merge pull request #2115 from seleniumbase/update-uc-mode-and-methods
Update UC Mode and add methods for verifying downloads via regex
2 parents 121aade + afc9253 commit 7464c4a

File tree

8 files changed

+156
-65
lines changed

8 files changed

+156
-65
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1339,7 +1339,7 @@ pytest --reruns=1 --reruns-delay=1
13391339
13401340
<div><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/cdn/img/fancy_logo_14.png" title="SeleniumBase" width="240" /></a></div> <div><a href="https://seleniumbase.io"><img src="https://img.shields.io/badge/docs-seleniumbase.io-11BBAA.svg" alt="SeleniumBase Docs" /></a></div> <div><a href="https://github.com/seleniumbase/SeleniumBase"><img src="https://img.shields.io/badge/tested%20with-SeleniumBase-04C38E.svg" alt="Tested with SeleniumBase" /></a></div> <div><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-22BBCC.svg" title="SeleniumBase" /></a> <a href="https://gitter.im/seleniumbase/SeleniumBase" target="_blank"><img src="https://img.shields.io/gitter/room/seleniumbase/SeleniumBase.svg" alt="Gitter chat"/></a></div>
13411341
<div><a href="https://pepy.tech/project/seleniumbase" target="_blank"><img src="https://static.pepy.tech/badge/seleniumbase" alt="SeleniumBase PyPI downloads" /></a></div>
1342-
<div><img src="https://visitor-badge.laobi.icu/badge?page_id=seleniumbase" alt="visitor badge"/></div>
1342+
<div><a href="https://github.com/seleniumbase/SeleniumBase"><img src="https://hits.dwyl.com/seleniumbase/hits.svg" alt="visitor badge"/></a> (since Sep 15, 2023)</div>
13431343
<div><a href="https://github.com/seleniumbase/SeleniumBase/stargazers"><img src="https://img.shields.io/github/stars/seleniumbase/seleniumbase.svg?color=19A57B" title="Stargazers" /></a></div>
13441344
13451345
--------

examples/uc_cdp_events.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
from pprint import pformat
22
from seleniumbase import BaseCase
3-
4-
if __name__ == "__main__":
5-
from pytest import main
6-
main([__file__, "--uc", "--uc-cdp", "-s"])
3+
BaseCase.main(__name__, __file__, "--uc", "--uc-cdp", "-s")
74

85

96
class CDPTests(BaseCase):

examples/verify_undetected.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
Some sites use scripts to detect Selenium, and then block you.
33
To evade detection, add --uc as a pytest command-line option."""
44
from seleniumbase import BaseCase
5-
6-
if __name__ == "__main__":
7-
from pytest import main
8-
main([__file__, "--uc", "-s"])
5+
BaseCase.main(__name__, __file__, "--uc", "-s")
96

107

118
class UndetectedTest(BaseCase):

help_docs/method_summary.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,11 +471,15 @@ self.get_path_of_downloaded_file(file, browser=False)
471471

472472
self.is_downloaded_file_present(file, browser=False)
473473

474+
self.is_downloaded_file_regex_present(regex, browser=False)
475+
474476
self.delete_downloaded_file_if_present(file, browser=False)
475477
# Duplicates: self.delete_downloaded_file(file, browser=False)
476478

477479
self.assert_downloaded_file(file, timeout=None, browser=False)
478480

481+
self.assert_downloaded_file_regex(regex, timeout=None, browser=False)
482+
479483
self.assert_true(expr, msg=None)
480484

481485
self.assert_false(expr, msg=None)

seleniumbase/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "4.18.6"
2+
__version__ = "4.18.7"

seleniumbase/core/browser_launcher.py

Lines changed: 80 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from selenium.webdriver.edge.service import Service as EdgeService
1717
from selenium.webdriver.firefox.service import Service as FirefoxService
1818
from selenium.webdriver.safari.service import Service as SafariService
19+
from seleniumbase import config as sb_config
1920
from seleniumbase import decorators
2021
from seleniumbase import drivers # webdriver storage folder for SeleniumBase
2122
from seleniumbase import extensions # browser extensions storage folder
@@ -1564,11 +1565,9 @@ def get_remote_driver(
15641565
extra_caps = {}
15651566
if cap_file:
15661567
from seleniumbase.core import capabilities_parser
1567-
15681568
desired_caps = capabilities_parser.get_desired_capabilities(cap_file)
15691569
if cap_string:
15701570
import json
1571-
15721571
try:
15731572
extra_caps = json.loads(str(cap_string))
15741573
except Exception as e:
@@ -2073,7 +2072,6 @@ def get_local_driver(
20732072
"IE Browser is for Windows-based systems only!"
20742073
)
20752074
from selenium.webdriver.ie.options import Options
2076-
20772075
ie_options = Options()
20782076
ie_options.ignore_protected_mode_settings = True
20792077
ie_options.ignore_zoom_level = True
@@ -2726,8 +2724,6 @@ def get_local_driver(
27262724
if is_using_uc(undetectable, browser_name):
27272725
uc_driver_version = get_uc_driver_version()
27282726
if multi_proxy:
2729-
from seleniumbase import config as sb_config
2730-
27312727
sb_config.multi_proxy = True
27322728
use_version = find_chromedriver_version_to_use(
27332729
use_version, driver_version
@@ -2983,7 +2979,6 @@ def get_local_driver(
29832979
if is_using_uc(undetectable, browser_name):
29842980
from seleniumbase import undetected
29852981
from urllib.error import URLError
2986-
29872982
if IS_LINUX:
29882983
if "--headless" in (
29892984
chrome_options.arguments
@@ -3007,52 +3002,70 @@ def get_local_driver(
30073002
chrome_options.add_experimental_option(
30083003
"w3c", True
30093004
)
3005+
if (
3006+
(not user_agent or "Headless" in user_agent)
3007+
and uc_chrome_version
3008+
and uc_chrome_version >= 117
3009+
and (headless or headless2)
3010+
and hasattr(sb_config, "uc_agent_cache")
3011+
):
3012+
user_agent = sb_config.uc_agent_cache
3013+
chrome_options.add_argument(
3014+
"--user-agent=%s" % user_agent
3015+
)
30103016
try:
30113017
if (
3012-
uc_chrome_version
3018+
(
3019+
not user_agent
3020+
or "Headless" in user_agent
3021+
)
3022+
and uc_chrome_version
30133023
and uc_chrome_version >= 117
30143024
and (headless or headless2)
3015-
and not user_agent
30163025
):
3026+
from seleniumbase.console_scripts import (
3027+
sb_install
3028+
)
3029+
sb_config.uc_user_agent_cache = True
30173030
headless_options = _set_chrome_options(
30183031
browser_name,
30193032
downloads_path,
30203033
True, # headless
30213034
locale_code,
3022-
proxy_string,
3023-
proxy_auth,
3024-
proxy_user,
3025-
proxy_pass,
3026-
proxy_bypass_list,
3027-
proxy_pac_url,
3028-
multi_proxy,
3029-
user_agent,
3030-
recorder_ext,
3035+
None, # proxy_string
3036+
None, # proxy_auth
3037+
None, # proxy_user
3038+
None, # proxy_pass
3039+
None, # proxy_bypass_list
3040+
None, # proxy_pac_url
3041+
None, # multi_proxy
3042+
None, # user_agent
3043+
None, # recorder_ext
30313044
disable_js,
30323045
disable_csp,
30333046
enable_ws,
30343047
enable_sync,
30353048
use_auto_ext,
3036-
False, # Undetectable
3037-
uc_cdp_events,
3038-
uc_subprocess,
3049+
False, # undetectable
3050+
False, # uc_cdp_events
3051+
False, # uc_subprocess
30393052
no_sandbox,
30403053
disable_gpu,
30413054
False, # headless2
30423055
incognito,
30433056
guest_mode,
30443057
dark_mode,
3045-
devtools,
3058+
None, # devtools
30463059
remote_debug,
30473060
enable_3d_apis,
30483061
swiftshader,
3049-
ad_block_on,
3062+
None, # ad_block_on
30503063
block_images,
30513064
do_not_track,
3052-
chromium_arg,
3053-
user_data_dir,
3054-
extension_zip,
3055-
extension_dir,
3065+
None, # chromium_arg
3066+
None, # user_data_dir
3067+
None, # extension_zip
3068+
None, # extension_dir
30563069
binary_location,
30573070
driver_version,
30583071
page_load_strategy,
@@ -3064,7 +3077,17 @@ def get_local_driver(
30643077
device_height,
30653078
device_pixel_ratio,
30663079
)
3067-
if not path_chromedriver:
3080+
if (
3081+
not path_chromedriver
3082+
or (
3083+
ch_driver_version
3084+
and use_version
3085+
and (
3086+
int(ch_driver_version)
3087+
< int(use_version)
3088+
)
3089+
)
3090+
):
30683091
sb_install.main(
30693092
override="chromedriver %s"
30703093
% use_version,
@@ -3091,12 +3114,16 @@ def get_local_driver(
30913114
service=service,
30923115
options=headless_options,
30933116
)
3094-
user_agent = driver.execute_script(
3095-
"return navigator.userAgent;"
3096-
).replace("Headless", "")
3097-
chrome_options.add_argument(
3098-
"--user-agent=%s" % user_agent
3099-
)
3117+
try:
3118+
user_agent = driver.execute_script(
3119+
"return navigator.userAgent;"
3120+
).replace("Headless", "")
3121+
chrome_options.add_argument(
3122+
"--user-agent=%s" % user_agent
3123+
)
3124+
sb_config.uc_agent_cache = user_agent
3125+
except Exception:
3126+
pass
31003127
driver.quit()
31013128
except Exception:
31023129
pass
@@ -3213,46 +3240,45 @@ def get_local_driver(
32133240
mcv = find_chromedriver_version_to_use(
32143241
mcv, driver_version
32153242
)
3216-
headless = True
32173243
headless_options = _set_chrome_options(
32183244
browser_name,
32193245
downloads_path,
3220-
headless,
3246+
True, # headless
32213247
locale_code,
3222-
proxy_string,
3223-
proxy_auth,
3224-
proxy_user,
3225-
proxy_pass,
3226-
proxy_bypass_list,
3227-
proxy_pac_url,
3228-
multi_proxy,
3229-
user_agent,
3230-
recorder_ext,
3248+
None, # proxy_string
3249+
None, # proxy_auth
3250+
None, # proxy_user
3251+
None, # proxy_pass
3252+
None, # proxy_bypass_list
3253+
None, # proxy_pac_url
3254+
None, # multi_proxy
3255+
None, # user_agent
3256+
None, # recorder_ext
32313257
disable_js,
32323258
disable_csp,
32333259
enable_ws,
32343260
enable_sync,
32353261
use_auto_ext,
3236-
undetectable,
3237-
uc_cdp_events,
3238-
uc_subprocess,
3262+
False, # undetectable
3263+
False, # uc_cdp_events
3264+
False, # uc_subprocess
32393265
no_sandbox,
32403266
disable_gpu,
3241-
headless2,
3267+
False, # headless2
32423268
incognito,
32433269
guest_mode,
32443270
dark_mode,
3245-
devtools,
3271+
None, # devtools
32463272
remote_debug,
32473273
enable_3d_apis,
32483274
swiftshader,
3249-
ad_block_on,
3275+
None, # ad_block_on
32503276
block_images,
32513277
do_not_track,
3252-
chromium_arg,
3253-
user_data_dir,
3254-
extension_zip,
3255-
extension_dir,
3278+
None, # chromium_arg
3279+
None, # user_data_dir
3280+
None, # extension_zip
3281+
None, # extension_dir
32563282
binary_location,
32573283
driver_version,
32583284
page_load_strategy,

seleniumbase/fixtures/base_case.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6828,6 +6828,19 @@ def is_downloaded_file_present(self, file, browser=False):
68286828
self.get_path_of_downloaded_file(file, browser=browser)
68296829
)
68306830

6831+
def is_downloaded_file_regex_present(self, regex, browser=False):
6832+
"""Returns True if the filename regex exists in the [Downloads Folder].
6833+
Uses Python regex via the "re" library for string-matching on the name.
6834+
@Params
6835+
regex - The filename regex of the downloaded file.
6836+
browser - If True, uses the path set by click-initiated downloads.
6837+
If False, uses the self.download_file(file_url) path.
6838+
Those paths are often the same. (browser-dependent)
6839+
(Default: False)."""
6840+
df = self.get_downloads_folder()
6841+
matches = [fn for fn in os.listdir(df) if re.match(regex, fn)]
6842+
return len(matches) >= 1
6843+
68316844
def delete_downloaded_file_if_present(self, file, browser=False):
68326845
"""Deletes the file from the [Downloads Folder] if the file exists.
68336846
For browser click-initiated downloads, SeleniumBase will override
@@ -6930,6 +6943,60 @@ def assert_downloaded_file(self, file, timeout=None, browser=False):
69306943
except Exception:
69316944
pass
69326945

6946+
def assert_downloaded_file_regex(self, regex, timeout=None, browser=False):
6947+
"""Assert the filename regex exists in SeleniumBase's Downloads Folder.
6948+
Uses Python regex via the "re" library for string-matching on the name.
6949+
@Params
6950+
regex - The filename regex of the downloaded file.
6951+
timeout - The time (seconds) to wait for the download to complete.
6952+
browser - If True, uses the path set by click-initiated downloads.
6953+
If False, uses the self.download_file(file_url) path.
6954+
Those paths are often the same. (browser-dependent)
6955+
(Default: False)."""
6956+
self.__check_scope()
6957+
if not timeout:
6958+
timeout = settings.LARGE_TIMEOUT
6959+
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
6960+
timeout = self.__get_new_timeout(timeout)
6961+
start_ms = time.time() * 1000.0
6962+
stop_ms = start_ms + (timeout * 1000.0)
6963+
found = False
6964+
df = self.get_downloads_folder()
6965+
for x in range(int(timeout)):
6966+
shared_utils.check_if_time_limit_exceeded()
6967+
try:
6968+
matches = [fn for fn in os.listdir(df) if re.match(regex, fn)]
6969+
self.assertTrue(
6970+
len(matches) >= 1,
6971+
"Regex [%s] was not found in the downloads folder [%s]!"
6972+
% (regex, self.get_downloads_folder()),
6973+
)
6974+
found = True
6975+
break
6976+
except Exception:
6977+
now_ms = time.time() * 1000.0
6978+
if now_ms >= stop_ms:
6979+
break
6980+
time.sleep(1)
6981+
if not found:
6982+
message = (
6983+
"Regex {%s} was not found in the downloads folder {%s} "
6984+
"after %s seconds! (Or the download didn't complete!)"
6985+
% (regex, self.get_downloads_folder(), timeout)
6986+
)
6987+
page_actions.timeout_exception("NoSuchFileException", message)
6988+
if self.demo_mode:
6989+
messenger_post = (
6990+
"<b>ASSERT DOWNLOADED FILE REGEX</b>: [%s]" % regex
6991+
)
6992+
try:
6993+
js_utils.activate_jquery(self.driver)
6994+
js_utils.post_messenger_success_message(
6995+
self.driver, messenger_post, self.message_duration
6996+
)
6997+
except Exception:
6998+
pass
6999+
69337000
def assert_true(self, expr, msg=None):
69347001
"""Asserts that the expression is True.
69357002
Will raise an exception if the statement if False."""

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@
238238
# (An optional library for image-processing.)
239239
"pillow": [
240240
'Pillow==9.5.0;python_version<"3.8"',
241-
'Pillow==10.0.0;python_version>="3.8"',
241+
'Pillow==10.0.1;python_version>="3.8"',
242242
],
243243
# pip install -e .[psutil]
244244
"psutil": [

0 commit comments

Comments
 (0)