seleniumbase 4.24.11__py3-none-any.whl → 4.33.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sbase/__init__.py +1 -0
 - sbase/steps.py +7 -0
 - seleniumbase/__init__.py +16 -7
 - seleniumbase/__version__.py +1 -1
 - seleniumbase/behave/behave_sb.py +97 -32
 - seleniumbase/common/decorators.py +16 -7
 - seleniumbase/config/proxy_list.py +3 -3
 - seleniumbase/config/settings.py +4 -0
 - seleniumbase/console_scripts/logo_helper.py +47 -8
 - seleniumbase/console_scripts/run.py +345 -335
 - seleniumbase/console_scripts/sb_behave_gui.py +5 -12
 - seleniumbase/console_scripts/sb_caseplans.py +6 -13
 - seleniumbase/console_scripts/sb_commander.py +5 -12
 - seleniumbase/console_scripts/sb_install.py +62 -54
 - seleniumbase/console_scripts/sb_mkchart.py +13 -20
 - seleniumbase/console_scripts/sb_mkdir.py +11 -17
 - seleniumbase/console_scripts/sb_mkfile.py +69 -43
 - seleniumbase/console_scripts/sb_mkpres.py +13 -20
 - seleniumbase/console_scripts/sb_mkrec.py +88 -21
 - seleniumbase/console_scripts/sb_objectify.py +30 -30
 - seleniumbase/console_scripts/sb_print.py +5 -12
 - seleniumbase/console_scripts/sb_recorder.py +16 -11
 - seleniumbase/core/browser_launcher.py +1658 -221
 - seleniumbase/core/log_helper.py +42 -27
 - seleniumbase/core/mysql.py +1 -4
 - seleniumbase/core/proxy_helper.py +35 -30
 - seleniumbase/core/recorder_helper.py +24 -5
 - seleniumbase/core/sb_cdp.py +1951 -0
 - seleniumbase/core/sb_driver.py +162 -8
 - seleniumbase/core/settings_parser.py +6 -0
 - seleniumbase/core/style_sheet.py +10 -0
 - seleniumbase/extensions/recorder.zip +0 -0
 - seleniumbase/fixtures/base_case.py +1225 -614
 - seleniumbase/fixtures/constants.py +10 -1
 - seleniumbase/fixtures/js_utils.py +171 -144
 - seleniumbase/fixtures/page_actions.py +177 -13
 - seleniumbase/fixtures/page_utils.py +25 -53
 - seleniumbase/fixtures/shared_utils.py +97 -11
 - seleniumbase/js_code/active_css_js.py +1 -1
 - seleniumbase/js_code/recorder_js.py +1 -1
 - seleniumbase/plugins/base_plugin.py +2 -3
 - seleniumbase/plugins/driver_manager.py +340 -65
 - seleniumbase/plugins/pytest_plugin.py +276 -47
 - seleniumbase/plugins/sb_manager.py +412 -99
 - seleniumbase/plugins/selenium_plugin.py +122 -17
 - seleniumbase/translate/translator.py +0 -7
 - seleniumbase/undetected/__init__.py +59 -52
 - seleniumbase/undetected/cdp.py +0 -1
 - seleniumbase/undetected/cdp_driver/__init__.py +1 -0
 - seleniumbase/undetected/cdp_driver/_contradict.py +110 -0
 - seleniumbase/undetected/cdp_driver/browser.py +829 -0
 - seleniumbase/undetected/cdp_driver/cdp_util.py +458 -0
 - seleniumbase/undetected/cdp_driver/config.py +334 -0
 - seleniumbase/undetected/cdp_driver/connection.py +639 -0
 - seleniumbase/undetected/cdp_driver/element.py +1168 -0
 - seleniumbase/undetected/cdp_driver/tab.py +1323 -0
 - seleniumbase/undetected/dprocess.py +4 -7
 - seleniumbase/undetected/options.py +6 -8
 - seleniumbase/undetected/patcher.py +11 -13
 - seleniumbase/undetected/reactor.py +0 -1
 - seleniumbase/undetected/webelement.py +16 -3
 - {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/LICENSE +1 -1
 - {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/METADATA +299 -252
 - {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/RECORD +67 -69
 - {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/WHEEL +1 -1
 - sbase/ReadMe.txt +0 -2
 - seleniumbase/ReadMe.md +0 -25
 - seleniumbase/common/ReadMe.md +0 -71
 - seleniumbase/console_scripts/ReadMe.md +0 -731
 - seleniumbase/drivers/ReadMe.md +0 -27
 - seleniumbase/extensions/ReadMe.md +0 -12
 - seleniumbase/masterqa/ReadMe.md +0 -61
 - seleniumbase/resources/ReadMe.md +0 -31
 - seleniumbase/resources/favicon.ico +0 -0
 - seleniumbase/utilities/selenium_grid/ReadMe.md +0 -84
 - seleniumbase/utilities/selenium_ide/ReadMe.md +0 -111
 - {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/entry_points.txt +0 -0
 - {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/top_level.txt +0 -0
 
| 
         @@ -16,7 +16,7 @@ def get_domain_url(url): 
     | 
|
| 
       16 
16 
     | 
    
         
             
                Into this:
         
     | 
| 
       17 
17 
     | 
    
         
             
                https://blog.xkcd.com
         
     | 
| 
       18 
18 
     | 
    
         
             
                """
         
     | 
| 
       19 
     | 
    
         
            -
                if not url.startswith("http://" 
     | 
| 
      
 19 
     | 
    
         
            +
                if not url.startswith(("http://", "https://")):
         
     | 
| 
       20 
20 
     | 
    
         
             
                    return url
         
     | 
| 
       21 
21 
     | 
    
         
             
                url_header = url.split("://")[0]
         
     | 
| 
       22 
22 
     | 
    
         
             
                simple_url = url.split("://")[1]
         
     | 
| 
         @@ -40,45 +40,25 @@ def swap_selector_and_by_if_reversed(selector, by): 
     | 
|
| 
       40 
40 
     | 
    
         | 
| 
       41 
41 
     | 
    
         
             
            def is_xpath_selector(selector):
         
     | 
| 
       42 
42 
     | 
    
         
             
                """Determine if a selector is an xpath selector."""
         
     | 
| 
       43 
     | 
    
         
            -
                 
     | 
| 
       44 
     | 
    
         
            -
                    selector.startswith("/")
         
     | 
| 
       45 
     | 
    
         
            -
                    or selector.startswith("./")
         
     | 
| 
       46 
     | 
    
         
            -
                    or selector.startswith("(")
         
     | 
| 
       47 
     | 
    
         
            -
                ):
         
     | 
| 
       48 
     | 
    
         
            -
                    return True
         
     | 
| 
       49 
     | 
    
         
            -
                return False
         
     | 
| 
      
 43 
     | 
    
         
            +
                return selector.startswith(("/", "./", "("))
         
     | 
| 
       50 
44 
     | 
    
         | 
| 
       51 
45 
     | 
    
         | 
| 
       52 
46 
     | 
    
         
             
            def is_link_text_selector(selector):
         
     | 
| 
       53 
47 
     | 
    
         
             
                """Determine if a selector is a link text selector."""
         
     | 
| 
       54 
     | 
    
         
            -
                 
     | 
| 
       55 
     | 
    
         
            -
                    selector.startswith("link=")
         
     | 
| 
       56 
     | 
    
         
            -
                    or selector.startswith("link_text=")
         
     | 
| 
       57 
     | 
    
         
            -
                    or selector.startswith("text=")
         
     | 
| 
       58 
     | 
    
         
            -
                ):
         
     | 
| 
       59 
     | 
    
         
            -
                    return True
         
     | 
| 
       60 
     | 
    
         
            -
                return False
         
     | 
| 
      
 48 
     | 
    
         
            +
                return selector.startswith(("link=", "link_text=", "text="))
         
     | 
| 
       61 
49 
     | 
    
         | 
| 
       62 
50 
     | 
    
         | 
| 
       63 
51 
     | 
    
         
             
            def is_partial_link_text_selector(selector):
         
     | 
| 
       64 
52 
     | 
    
         
             
                """Determine if a selector is a partial link text selector."""
         
     | 
| 
       65 
     | 
    
         
            -
                 
     | 
| 
       66 
     | 
    
         
            -
                     
     | 
| 
       67 
     | 
    
         
            -
                     
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
                    or selector.startswith("p_link=")
         
     | 
| 
       70 
     | 
    
         
            -
                    or selector.startswith("p_link_text=")
         
     | 
| 
       71 
     | 
    
         
            -
                    or selector.startswith("p_text=")
         
     | 
| 
       72 
     | 
    
         
            -
                ):
         
     | 
| 
       73 
     | 
    
         
            -
                    return True
         
     | 
| 
       74 
     | 
    
         
            -
                return False
         
     | 
| 
      
 53 
     | 
    
         
            +
                return selector.startswith((
         
     | 
| 
      
 54 
     | 
    
         
            +
                    "partial_link=", "partial_link_text=", "partial_text=",
         
     | 
| 
      
 55 
     | 
    
         
            +
                    "p_link=", "p_link_text=", "p_text="
         
     | 
| 
      
 56 
     | 
    
         
            +
                ))
         
     | 
| 
       75 
57 
     | 
    
         | 
| 
       76 
58 
     | 
    
         | 
| 
       77 
59 
     | 
    
         
             
            def is_name_selector(selector):
         
     | 
| 
       78 
60 
     | 
    
         
             
                """Determine if a selector is a name selector."""
         
     | 
| 
       79 
     | 
    
         
            -
                 
     | 
| 
       80 
     | 
    
         
            -
                    return True
         
     | 
| 
       81 
     | 
    
         
            -
                return False
         
     | 
| 
      
 61 
     | 
    
         
            +
                return selector.startswith(("name=", "&"))
         
     | 
| 
       82 
62 
     | 
    
         | 
| 
       83 
63 
     | 
    
         | 
| 
       84 
64 
     | 
    
         
             
            def recalculate_selector(selector, by, xp_ok=True):
         
     | 
| 
         @@ -108,12 +88,18 @@ def recalculate_selector(selector, by, xp_ok=True): 
     | 
|
| 
       108 
88 
     | 
    
         
             
                    name = get_name_from_selector(selector)
         
     | 
| 
       109 
89 
     | 
    
         
             
                    selector = '[name="%s"]' % name
         
     | 
| 
       110 
90 
     | 
    
         
             
                    by = By.CSS_SELECTOR
         
     | 
| 
       111 
     | 
    
         
            -
                if xp_ok:
         
     | 
| 
       112 
     | 
    
         
            -
                     
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
                        by = By.XPATH
         
     | 
| 
      
 91 
     | 
    
         
            +
                if xp_ok and ":contains(" in selector and by == By.CSS_SELECTOR:
         
     | 
| 
      
 92 
     | 
    
         
            +
                    selector = css_to_xpath.convert_css_to_xpath(selector)
         
     | 
| 
      
 93 
     | 
    
         
            +
                    by = By.XPATH
         
     | 
| 
       115 
94 
     | 
    
         
             
                if by == "":
         
     | 
| 
       116 
95 
     | 
    
         
             
                    by = By.CSS_SELECTOR
         
     | 
| 
      
 96 
     | 
    
         
            +
                if not is_valid_by(by):
         
     | 
| 
      
 97 
     | 
    
         
            +
                    valid_by_options = [
         
     | 
| 
      
 98 
     | 
    
         
            +
                        "css selector", "link text", "partial link text",
         
     | 
| 
      
 99 
     | 
    
         
            +
                        "name", "xpath", "id", "tag name", "class name",
         
     | 
| 
      
 100 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 101 
     | 
    
         
            +
                    msg = "Choose a `by` from: %s." % valid_by_options
         
     | 
| 
      
 102 
     | 
    
         
            +
                    raise Exception('Invalid `by`: "%s"\n%s' % (by, msg))
         
     | 
| 
       117 
103 
     | 
    
         
             
                return (selector, by)
         
     | 
| 
       118 
104 
     | 
    
         | 
| 
       119 
105 
     | 
    
         | 
| 
         @@ -123,21 +109,10 @@ def looks_like_a_page_url(url): 
     | 
|
| 
       123 
109 
     | 
    
         
             
                possible typos when calling self.get(url), which will try to
         
     | 
| 
       124 
110 
     | 
    
         
             
                navigate to the page if a URL is detected, but will instead call
         
     | 
| 
       125 
111 
     | 
    
         
             
                self.get_element(URL_AS_A_SELECTOR) if the input is not a URL."""
         
     | 
| 
       126 
     | 
    
         
            -
                 
     | 
| 
       127 
     | 
    
         
            -
                     
     | 
| 
       128 
     | 
    
         
            -
                     
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
                    or url.startswith("about:")
         
     | 
| 
       131 
     | 
    
         
            -
                    or url.startswith("blob:")
         
     | 
| 
       132 
     | 
    
         
            -
                    or url.startswith("chrome:")
         
     | 
| 
       133 
     | 
    
         
            -
                    or url.startswith("data:")
         
     | 
| 
       134 
     | 
    
         
            -
                    or url.startswith("edge:")
         
     | 
| 
       135 
     | 
    
         
            -
                    or url.startswith("file:")
         
     | 
| 
       136 
     | 
    
         
            -
                    or url.startswith("view-source:")
         
     | 
| 
       137 
     | 
    
         
            -
                ):
         
     | 
| 
       138 
     | 
    
         
            -
                    return True
         
     | 
| 
       139 
     | 
    
         
            -
                else:
         
     | 
| 
       140 
     | 
    
         
            -
                    return False
         
     | 
| 
      
 112 
     | 
    
         
            +
                return url.startswith((
         
     | 
| 
      
 113 
     | 
    
         
            +
                    "http:", "https:", "://", "about:", "blob:", "chrome:",
         
     | 
| 
      
 114 
     | 
    
         
            +
                    "data:", "edge:", "file:", "view-source:"
         
     | 
| 
      
 115 
     | 
    
         
            +
                ))
         
     | 
| 
       141 
116 
     | 
    
         | 
| 
       142 
117 
     | 
    
         | 
| 
       143 
118 
     | 
    
         
             
            def get_link_text_from_selector(selector):
         
     | 
| 
         @@ -190,12 +165,9 @@ def is_valid_url(url): 
     | 
|
| 
       190 
165 
     | 
    
         
             
                )
         
     | 
| 
       191 
166 
     | 
    
         
             
                if (
         
     | 
| 
       192 
167 
     | 
    
         
             
                    regex.match(url)
         
     | 
| 
       193 
     | 
    
         
            -
                    or url.startswith( 
     | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
       195 
     | 
    
         
            -
                     
     | 
| 
       196 
     | 
    
         
            -
                    or url.startswith("data:")
         
     | 
| 
       197 
     | 
    
         
            -
                    or url.startswith("edge:")
         
     | 
| 
       198 
     | 
    
         
            -
                    or url.startswith("file:")
         
     | 
| 
      
 168 
     | 
    
         
            +
                    or url.startswith((
         
     | 
| 
      
 169 
     | 
    
         
            +
                        "about:", "blob:", "chrome:", "data:", "edge:", "file:"
         
     | 
| 
      
 170 
     | 
    
         
            +
                    ))
         
     | 
| 
       199 
171 
     | 
    
         
             
                ):
         
     | 
| 
       200 
172 
     | 
    
         
             
                    return True
         
     | 
| 
       201 
173 
     | 
    
         
             
                else:
         
     | 
| 
         @@ -1,8 +1,11 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            """Shared utility methods"""
         
     | 
| 
      
 2 
     | 
    
         
            +
            import colorama
         
     | 
| 
       2 
3 
     | 
    
         
             
            import os
         
     | 
| 
      
 4 
     | 
    
         
            +
            import pathlib
         
     | 
| 
       3 
5 
     | 
    
         
             
            import platform
         
     | 
| 
       4 
6 
     | 
    
         
             
            import sys
         
     | 
| 
       5 
7 
     | 
    
         
             
            import time
         
     | 
| 
      
 8 
     | 
    
         
            +
            from contextlib import suppress
         
     | 
| 
       6 
9 
     | 
    
         
             
            from seleniumbase import config as sb_config
         
     | 
| 
       7 
10 
     | 
    
         
             
            from seleniumbase.fixtures import constants
         
     | 
| 
       8 
11 
     | 
    
         | 
| 
         @@ -67,6 +70,89 @@ def get_terminal_width(): 
     | 
|
| 
       67 
70 
     | 
    
         
             
                return width
         
     | 
| 
       68 
71 
     | 
    
         | 
| 
       69 
72 
     | 
    
         | 
| 
      
 73 
     | 
    
         
            +
            def fix_colorama_if_windows():
         
     | 
| 
      
 74 
     | 
    
         
            +
                if is_windows():
         
     | 
| 
      
 75 
     | 
    
         
            +
                    colorama.just_fix_windows_console()
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            def fix_url_as_needed(url):
         
     | 
| 
      
 79 
     | 
    
         
            +
                if not url:
         
     | 
| 
      
 80 
     | 
    
         
            +
                    url = "data:,"
         
     | 
| 
      
 81 
     | 
    
         
            +
                elif url.startswith("//"):
         
     | 
| 
      
 82 
     | 
    
         
            +
                    url = "https:" + url
         
     | 
| 
      
 83 
     | 
    
         
            +
                elif ":" not in url:
         
     | 
| 
      
 84 
     | 
    
         
            +
                    url = "https://" + url
         
     | 
| 
      
 85 
     | 
    
         
            +
                return url
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
            def reconnect_if_disconnected(driver):
         
     | 
| 
      
 89 
     | 
    
         
            +
                if (
         
     | 
| 
      
 90 
     | 
    
         
            +
                    hasattr(driver, "_is_using_uc")
         
     | 
| 
      
 91 
     | 
    
         
            +
                    and driver._is_using_uc
         
     | 
| 
      
 92 
     | 
    
         
            +
                    and hasattr(driver, "is_connected")
         
     | 
| 
      
 93 
     | 
    
         
            +
                    and not driver.is_connected()
         
     | 
| 
      
 94 
     | 
    
         
            +
                ):
         
     | 
| 
      
 95 
     | 
    
         
            +
                    with suppress(Exception):
         
     | 
| 
      
 96 
     | 
    
         
            +
                        driver.connect()
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            def is_cdp_swap_needed(driver):
         
     | 
| 
      
 100 
     | 
    
         
            +
                """
         
     | 
| 
      
 101 
     | 
    
         
            +
                When someone is using CDP Mode with a disconnected webdriver,
         
     | 
| 
      
 102 
     | 
    
         
            +
                but they forget to reconnect before calling a webdriver method,
         
     | 
| 
      
 103 
     | 
    
         
            +
                this method is used to substitute the webdriver method for a
         
     | 
| 
      
 104 
     | 
    
         
            +
                CDP Mode method instead, which keeps CDP Stealth Mode enabled.
         
     | 
| 
      
 105 
     | 
    
         
            +
                For other webdriver methods, SeleniumBase will reconnect first.
         
     | 
| 
      
 106 
     | 
    
         
            +
                """
         
     | 
| 
      
 107 
     | 
    
         
            +
                return (
         
     | 
| 
      
 108 
     | 
    
         
            +
                    hasattr(driver, "is_cdp_mode_active")
         
     | 
| 
      
 109 
     | 
    
         
            +
                    and driver.is_cdp_mode_active()
         
     | 
| 
      
 110 
     | 
    
         
            +
                    and hasattr(driver, "is_connected")
         
     | 
| 
      
 111 
     | 
    
         
            +
                    and not driver.is_connected()
         
     | 
| 
      
 112 
     | 
    
         
            +
                )
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
            def is_chrome_130_or_newer(self, binary_location=None):
         
     | 
| 
      
 116 
     | 
    
         
            +
                from seleniumbase.core import detect_b_ver
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                """Due to changes in Chrome-130, UC Mode freezes at start-up
         
     | 
| 
      
 119 
     | 
    
         
            +
                unless the user-data-dir already exists and is populated."""
         
     | 
| 
      
 120 
     | 
    
         
            +
                with suppress(Exception):
         
     | 
| 
      
 121 
     | 
    
         
            +
                    if not binary_location:
         
     | 
| 
      
 122 
     | 
    
         
            +
                        ver = detect_b_ver.get_browser_version_from_os("google-chrome")
         
     | 
| 
      
 123 
     | 
    
         
            +
                    else:
         
     | 
| 
      
 124 
     | 
    
         
            +
                        ver = detect_b_ver.get_browser_version_from_binary(
         
     | 
| 
      
 125 
     | 
    
         
            +
                            binary_location
         
     | 
| 
      
 126 
     | 
    
         
            +
                        )
         
     | 
| 
      
 127 
     | 
    
         
            +
                    if ver and len(ver) > 3 and int(ver.split(".")[0]) >= 130:
         
     | 
| 
      
 128 
     | 
    
         
            +
                        return True
         
     | 
| 
      
 129 
     | 
    
         
            +
                return False
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
            def make_dir_files_writable(dir_path):
         
     | 
| 
      
 133 
     | 
    
         
            +
                # Make all files in the given directory writable.
         
     | 
| 
      
 134 
     | 
    
         
            +
                for file_path in pathlib.Path(dir_path).glob("*"):
         
     | 
| 
      
 135 
     | 
    
         
            +
                    if file_path.is_file():
         
     | 
| 
      
 136 
     | 
    
         
            +
                        mode = os.stat(file_path).st_mode
         
     | 
| 
      
 137 
     | 
    
         
            +
                        mode |= (mode & 0o444) >> 1  # copy R bits to W
         
     | 
| 
      
 138 
     | 
    
         
            +
                        with suppress(Exception):
         
     | 
| 
      
 139 
     | 
    
         
            +
                            os.chmod(file_path, mode)
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
            def make_writable(file_path):
         
     | 
| 
      
 143 
     | 
    
         
            +
                # Set permissions to: "If you can read it, you can write it."
         
     | 
| 
      
 144 
     | 
    
         
            +
                mode = os.stat(file_path).st_mode
         
     | 
| 
      
 145 
     | 
    
         
            +
                mode |= (mode & 0o444) >> 1  # copy R bits to W
         
     | 
| 
      
 146 
     | 
    
         
            +
                os.chmod(file_path, mode)
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
            def make_executable(file_path):
         
     | 
| 
      
 150 
     | 
    
         
            +
                # Set permissions to: "If you can read it, you can execute it."
         
     | 
| 
      
 151 
     | 
    
         
            +
                mode = os.stat(file_path).st_mode
         
     | 
| 
      
 152 
     | 
    
         
            +
                mode |= (mode & 0o444) >> 2  # copy R bits to X
         
     | 
| 
      
 153 
     | 
    
         
            +
                os.chmod(file_path, mode)
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
       70 
156 
     | 
    
         
             
            def format_exc(exception, message):
         
     | 
| 
       71 
157 
     | 
    
         
             
                """Formats an exception message to make the output cleaner."""
         
     | 
| 
       72 
158 
     | 
    
         
             
                from selenium.common.exceptions import ElementNotVisibleException
         
     | 
| 
         @@ -81,46 +167,46 @@ def format_exc(exception, message): 
     | 
|
| 
       81 
167 
     | 
    
         
             
                from seleniumbase.common.exceptions import TextNotVisibleException
         
     | 
| 
       82 
168 
     | 
    
         
             
                from seleniumbase.common import exceptions
         
     | 
| 
       83 
169 
     | 
    
         | 
| 
       84 
     | 
    
         
            -
                if exception  
     | 
| 
      
 170 
     | 
    
         
            +
                if exception is Exception:
         
     | 
| 
       85 
171 
     | 
    
         
             
                    exc = Exception
         
     | 
| 
       86 
172 
     | 
    
         
             
                    return exc, message
         
     | 
| 
       87 
     | 
    
         
            -
                elif exception  
     | 
| 
      
 173 
     | 
    
         
            +
                elif exception is ElementNotVisibleException:
         
     | 
| 
       88 
174 
     | 
    
         
             
                    exc = exceptions.ElementNotVisibleException
         
     | 
| 
       89 
175 
     | 
    
         
             
                elif exception == "ElementNotVisibleException":
         
     | 
| 
       90 
176 
     | 
    
         
             
                    exc = exceptions.ElementNotVisibleException
         
     | 
| 
       91 
     | 
    
         
            -
                elif exception  
     | 
| 
      
 177 
     | 
    
         
            +
                elif exception is LinkTextNotFoundException:
         
     | 
| 
       92 
178 
     | 
    
         
             
                    exc = exceptions.LinkTextNotFoundException
         
     | 
| 
       93 
179 
     | 
    
         
             
                elif exception == "LinkTextNotFoundException":
         
     | 
| 
       94 
180 
     | 
    
         
             
                    exc = exceptions.LinkTextNotFoundException
         
     | 
| 
       95 
     | 
    
         
            -
                elif exception  
     | 
| 
      
 181 
     | 
    
         
            +
                elif exception is NoSuchElementException:
         
     | 
| 
       96 
182 
     | 
    
         
             
                    exc = exceptions.NoSuchElementException
         
     | 
| 
       97 
183 
     | 
    
         
             
                elif exception == "NoSuchElementException":
         
     | 
| 
       98 
184 
     | 
    
         
             
                    exc = exceptions.NoSuchElementException
         
     | 
| 
       99 
     | 
    
         
            -
                elif exception  
     | 
| 
      
 185 
     | 
    
         
            +
                elif exception is TextNotVisibleException:
         
     | 
| 
       100 
186 
     | 
    
         
             
                    exc = exceptions.TextNotVisibleException
         
     | 
| 
       101 
187 
     | 
    
         
             
                elif exception == "TextNotVisibleException":
         
     | 
| 
       102 
188 
     | 
    
         
             
                    exc = exceptions.TextNotVisibleException
         
     | 
| 
       103 
     | 
    
         
            -
                elif exception  
     | 
| 
      
 189 
     | 
    
         
            +
                elif exception is NoAlertPresentException:
         
     | 
| 
       104 
190 
     | 
    
         
             
                    exc = exceptions.NoAlertPresentException
         
     | 
| 
       105 
191 
     | 
    
         
             
                elif exception == "NoAlertPresentException":
         
     | 
| 
       106 
192 
     | 
    
         
             
                    exc = exceptions.NoAlertPresentException
         
     | 
| 
       107 
     | 
    
         
            -
                elif exception  
     | 
| 
      
 193 
     | 
    
         
            +
                elif exception is NoSuchAttributeException:
         
     | 
| 
       108 
194 
     | 
    
         
             
                    exc = exceptions.NoSuchAttributeException
         
     | 
| 
       109 
195 
     | 
    
         
             
                elif exception == "NoSuchAttributeException":
         
     | 
| 
       110 
196 
     | 
    
         
             
                    exc = exceptions.NoSuchAttributeException
         
     | 
| 
       111 
     | 
    
         
            -
                elif exception  
     | 
| 
      
 197 
     | 
    
         
            +
                elif exception is NoSuchFrameException:
         
     | 
| 
       112 
198 
     | 
    
         
             
                    exc = exceptions.NoSuchFrameException
         
     | 
| 
       113 
199 
     | 
    
         
             
                elif exception == "NoSuchFrameException":
         
     | 
| 
       114 
200 
     | 
    
         
             
                    exc = exceptions.NoSuchFrameException
         
     | 
| 
       115 
     | 
    
         
            -
                elif exception  
     | 
| 
      
 201 
     | 
    
         
            +
                elif exception is NoSuchWindowException:
         
     | 
| 
       116 
202 
     | 
    
         
             
                    exc = exceptions.NoSuchWindowException
         
     | 
| 
       117 
203 
     | 
    
         
             
                elif exception == "NoSuchWindowException":
         
     | 
| 
       118 
204 
     | 
    
         
             
                    exc = exceptions.NoSuchWindowException
         
     | 
| 
       119 
     | 
    
         
            -
                elif exception  
     | 
| 
      
 205 
     | 
    
         
            +
                elif exception is NoSuchFileException:
         
     | 
| 
       120 
206 
     | 
    
         
             
                    exc = exceptions.NoSuchFileException
         
     | 
| 
       121 
207 
     | 
    
         
             
                elif exception == "NoSuchFileException":
         
     | 
| 
       122 
208 
     | 
    
         
             
                    exc = exceptions.NoSuchFileException
         
     | 
| 
       123 
     | 
    
         
            -
                elif exception  
     | 
| 
      
 209 
     | 
    
         
            +
                elif exception is NoSuchOptionException:
         
     | 
| 
       124 
210 
     | 
    
         
             
                    exc = exceptions.NoSuchOptionException
         
     | 
| 
       125 
211 
     | 
    
         
             
                elif exception == "NoSuchOptionException":
         
     | 
| 
       126 
212 
     | 
    
         
             
                    exc = exceptions.NoSuchOptionException
         
     | 
| 
         @@ -2,6 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         
             
            import ast
         
     | 
| 
       3 
3 
     | 
    
         
             
            import sys
         
     | 
| 
       4 
4 
     | 
    
         
             
            import time
         
     | 
| 
      
 5 
     | 
    
         
            +
            from contextlib import suppress
         
     | 
| 
       5 
6 
     | 
    
         
             
            from nose.plugins import Plugin
         
     | 
| 
       6 
7 
     | 
    
         
             
            from seleniumbase import config as sb_config
         
     | 
| 
       7 
8 
     | 
    
         
             
            from seleniumbase.config import settings
         
     | 
| 
         @@ -305,14 +306,12 @@ class Base(Plugin): 
     | 
|
| 
       305 
306 
     | 
    
         
             
                    if python3_11_or_newer and py311_patch2:
         
     | 
| 
       306 
307 
     | 
    
         
             
                        # Handle a bug on Python 3.11 where exceptions aren't seen
         
     | 
| 
       307 
308 
     | 
    
         
             
                        sb_config._browser_version = None
         
     | 
| 
       308 
     | 
    
         
            -
                         
     | 
| 
      
 309 
     | 
    
         
            +
                        with suppress(Exception):
         
     | 
| 
       309 
310 
     | 
    
         
             
                            test._BaseCase__set_last_page_screenshot()
         
     | 
| 
       310 
311 
     | 
    
         
             
                            test._BaseCase__set_last_page_url()
         
     | 
| 
       311 
312 
     | 
    
         
             
                            test._BaseCase__set_last_page_source()
         
     | 
| 
       312 
313 
     | 
    
         
             
                            sb_config._browser_version = test._get_browser_version()
         
     | 
| 
       313 
314 
     | 
    
         
             
                            test._log_fail_data()
         
     | 
| 
       314 
     | 
    
         
            -
                        except Exception:
         
     | 
| 
       315 
     | 
    
         
            -
                            pass
         
     | 
| 
       316 
315 
     | 
    
         
             
                        sb_config._excinfo_tb = err
         
     | 
| 
       317 
316 
     | 
    
         
             
                        log_path = None
         
     | 
| 
       318 
317 
     | 
    
         
             
                        if hasattr(sb_config, "_test_logpath"):
         
     |