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.
Files changed (78) hide show
  1. sbase/__init__.py +1 -0
  2. sbase/steps.py +7 -0
  3. seleniumbase/__init__.py +16 -7
  4. seleniumbase/__version__.py +1 -1
  5. seleniumbase/behave/behave_sb.py +97 -32
  6. seleniumbase/common/decorators.py +16 -7
  7. seleniumbase/config/proxy_list.py +3 -3
  8. seleniumbase/config/settings.py +4 -0
  9. seleniumbase/console_scripts/logo_helper.py +47 -8
  10. seleniumbase/console_scripts/run.py +345 -335
  11. seleniumbase/console_scripts/sb_behave_gui.py +5 -12
  12. seleniumbase/console_scripts/sb_caseplans.py +6 -13
  13. seleniumbase/console_scripts/sb_commander.py +5 -12
  14. seleniumbase/console_scripts/sb_install.py +62 -54
  15. seleniumbase/console_scripts/sb_mkchart.py +13 -20
  16. seleniumbase/console_scripts/sb_mkdir.py +11 -17
  17. seleniumbase/console_scripts/sb_mkfile.py +69 -43
  18. seleniumbase/console_scripts/sb_mkpres.py +13 -20
  19. seleniumbase/console_scripts/sb_mkrec.py +88 -21
  20. seleniumbase/console_scripts/sb_objectify.py +30 -30
  21. seleniumbase/console_scripts/sb_print.py +5 -12
  22. seleniumbase/console_scripts/sb_recorder.py +16 -11
  23. seleniumbase/core/browser_launcher.py +1658 -221
  24. seleniumbase/core/log_helper.py +42 -27
  25. seleniumbase/core/mysql.py +1 -4
  26. seleniumbase/core/proxy_helper.py +35 -30
  27. seleniumbase/core/recorder_helper.py +24 -5
  28. seleniumbase/core/sb_cdp.py +1951 -0
  29. seleniumbase/core/sb_driver.py +162 -8
  30. seleniumbase/core/settings_parser.py +6 -0
  31. seleniumbase/core/style_sheet.py +10 -0
  32. seleniumbase/extensions/recorder.zip +0 -0
  33. seleniumbase/fixtures/base_case.py +1225 -614
  34. seleniumbase/fixtures/constants.py +10 -1
  35. seleniumbase/fixtures/js_utils.py +171 -144
  36. seleniumbase/fixtures/page_actions.py +177 -13
  37. seleniumbase/fixtures/page_utils.py +25 -53
  38. seleniumbase/fixtures/shared_utils.py +97 -11
  39. seleniumbase/js_code/active_css_js.py +1 -1
  40. seleniumbase/js_code/recorder_js.py +1 -1
  41. seleniumbase/plugins/base_plugin.py +2 -3
  42. seleniumbase/plugins/driver_manager.py +340 -65
  43. seleniumbase/plugins/pytest_plugin.py +276 -47
  44. seleniumbase/plugins/sb_manager.py +412 -99
  45. seleniumbase/plugins/selenium_plugin.py +122 -17
  46. seleniumbase/translate/translator.py +0 -7
  47. seleniumbase/undetected/__init__.py +59 -52
  48. seleniumbase/undetected/cdp.py +0 -1
  49. seleniumbase/undetected/cdp_driver/__init__.py +1 -0
  50. seleniumbase/undetected/cdp_driver/_contradict.py +110 -0
  51. seleniumbase/undetected/cdp_driver/browser.py +829 -0
  52. seleniumbase/undetected/cdp_driver/cdp_util.py +458 -0
  53. seleniumbase/undetected/cdp_driver/config.py +334 -0
  54. seleniumbase/undetected/cdp_driver/connection.py +639 -0
  55. seleniumbase/undetected/cdp_driver/element.py +1168 -0
  56. seleniumbase/undetected/cdp_driver/tab.py +1323 -0
  57. seleniumbase/undetected/dprocess.py +4 -7
  58. seleniumbase/undetected/options.py +6 -8
  59. seleniumbase/undetected/patcher.py +11 -13
  60. seleniumbase/undetected/reactor.py +0 -1
  61. seleniumbase/undetected/webelement.py +16 -3
  62. {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/LICENSE +1 -1
  63. {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/METADATA +299 -252
  64. {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/RECORD +67 -69
  65. {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/WHEEL +1 -1
  66. sbase/ReadMe.txt +0 -2
  67. seleniumbase/ReadMe.md +0 -25
  68. seleniumbase/common/ReadMe.md +0 -71
  69. seleniumbase/console_scripts/ReadMe.md +0 -731
  70. seleniumbase/drivers/ReadMe.md +0 -27
  71. seleniumbase/extensions/ReadMe.md +0 -12
  72. seleniumbase/masterqa/ReadMe.md +0 -61
  73. seleniumbase/resources/ReadMe.md +0 -31
  74. seleniumbase/resources/favicon.ico +0 -0
  75. seleniumbase/utilities/selenium_grid/ReadMe.md +0 -84
  76. seleniumbase/utilities/selenium_ide/ReadMe.md +0 -111
  77. {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/entry_points.txt +0 -0
  78. {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://") and not url.startswith("https://"):
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
- if (
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
- if (
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
- if (
66
- selector.startswith("partial_link=")
67
- or selector.startswith("partial_link_text=")
68
- or selector.startswith("partial_text=")
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
- if selector.startswith("name=") or selector.startswith("&"):
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
- if ":contains(" in selector and by == By.CSS_SELECTOR:
113
- selector = css_to_xpath.convert_css_to_xpath(selector)
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
- if (
127
- url.startswith("http:")
128
- or url.startswith("https:")
129
- or url.startswith("://")
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("about:")
194
- or url.startswith("blob:")
195
- or url.startswith("chrome:")
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 == Exception:
170
+ if exception is Exception:
85
171
  exc = Exception
86
172
  return exc, message
87
- elif exception == ElementNotVisibleException:
173
+ elif exception is ElementNotVisibleException:
88
174
  exc = exceptions.ElementNotVisibleException
89
175
  elif exception == "ElementNotVisibleException":
90
176
  exc = exceptions.ElementNotVisibleException
91
- elif exception == LinkTextNotFoundException:
177
+ elif exception is LinkTextNotFoundException:
92
178
  exc = exceptions.LinkTextNotFoundException
93
179
  elif exception == "LinkTextNotFoundException":
94
180
  exc = exceptions.LinkTextNotFoundException
95
- elif exception == NoSuchElementException:
181
+ elif exception is NoSuchElementException:
96
182
  exc = exceptions.NoSuchElementException
97
183
  elif exception == "NoSuchElementException":
98
184
  exc = exceptions.NoSuchElementException
99
- elif exception == TextNotVisibleException:
185
+ elif exception is TextNotVisibleException:
100
186
  exc = exceptions.TextNotVisibleException
101
187
  elif exception == "TextNotVisibleException":
102
188
  exc = exceptions.TextNotVisibleException
103
- elif exception == NoAlertPresentException:
189
+ elif exception is NoAlertPresentException:
104
190
  exc = exceptions.NoAlertPresentException
105
191
  elif exception == "NoAlertPresentException":
106
192
  exc = exceptions.NoAlertPresentException
107
- elif exception == NoSuchAttributeException:
193
+ elif exception is NoSuchAttributeException:
108
194
  exc = exceptions.NoSuchAttributeException
109
195
  elif exception == "NoSuchAttributeException":
110
196
  exc = exceptions.NoSuchAttributeException
111
- elif exception == NoSuchFrameException:
197
+ elif exception is NoSuchFrameException:
112
198
  exc = exceptions.NoSuchFrameException
113
199
  elif exception == "NoSuchFrameException":
114
200
  exc = exceptions.NoSuchFrameException
115
- elif exception == NoSuchWindowException:
201
+ elif exception is NoSuchWindowException:
116
202
  exc = exceptions.NoSuchWindowException
117
203
  elif exception == "NoSuchWindowException":
118
204
  exc = exceptions.NoSuchWindowException
119
- elif exception == NoSuchFileException:
205
+ elif exception is NoSuchFileException:
120
206
  exc = exceptions.NoSuchFileException
121
207
  elif exception == "NoSuchFileException":
122
208
  exc = exceptions.NoSuchFileException
123
- elif exception == NoSuchOptionException:
209
+ elif exception is NoSuchOptionException:
124
210
  exc = exceptions.NoSuchOptionException
125
211
  elif exception == "NoSuchOptionException":
126
212
  exc = exceptions.NoSuchOptionException
@@ -103,7 +103,7 @@ function hasDigit(str) {
103
103
  return /\d/.test(str);
104
104
  };
105
105
  function isGen(str) {
106
- return /[_-]\d/.test(str);
106
+ return /[_-]\d/.test(str) || /\d[a-z]/.test(str);
107
107
  };
108
108
  function tagName(el) {
109
109
  return el.tagName.toLowerCase();
@@ -103,7 +103,7 @@ function hasDigit(str) {
103
103
  return /\d/.test(str);
104
104
  };
105
105
  function isGen(str) {
106
- return /[_-]\d/.test(str);
106
+ return /[_-]\d/.test(str) || /\d[a-z]/.test(str);
107
107
  };
108
108
  function tagName(el) {
109
109
  return el.tagName.toLowerCase();
@@ -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
- try:
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"):