seleniumbase 4.24.10__py3-none-any.whl → 4.33.15__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) 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/detect_b_ver.py +7 -8
  25. seleniumbase/core/log_helper.py +42 -27
  26. seleniumbase/core/mysql.py +1 -4
  27. seleniumbase/core/proxy_helper.py +35 -30
  28. seleniumbase/core/recorder_helper.py +24 -5
  29. seleniumbase/core/sb_cdp.py +1951 -0
  30. seleniumbase/core/sb_driver.py +162 -8
  31. seleniumbase/core/settings_parser.py +6 -0
  32. seleniumbase/core/style_sheet.py +10 -0
  33. seleniumbase/extensions/recorder.zip +0 -0
  34. seleniumbase/fixtures/base_case.py +1234 -632
  35. seleniumbase/fixtures/constants.py +10 -1
  36. seleniumbase/fixtures/js_utils.py +171 -144
  37. seleniumbase/fixtures/page_actions.py +177 -13
  38. seleniumbase/fixtures/page_utils.py +25 -53
  39. seleniumbase/fixtures/shared_utils.py +97 -11
  40. seleniumbase/js_code/active_css_js.py +1 -1
  41. seleniumbase/js_code/recorder_js.py +1 -1
  42. seleniumbase/plugins/base_plugin.py +2 -3
  43. seleniumbase/plugins/driver_manager.py +340 -65
  44. seleniumbase/plugins/pytest_plugin.py +276 -47
  45. seleniumbase/plugins/sb_manager.py +412 -99
  46. seleniumbase/plugins/selenium_plugin.py +122 -17
  47. seleniumbase/translate/translator.py +0 -7
  48. seleniumbase/undetected/__init__.py +59 -52
  49. seleniumbase/undetected/cdp.py +0 -1
  50. seleniumbase/undetected/cdp_driver/__init__.py +1 -0
  51. seleniumbase/undetected/cdp_driver/_contradict.py +110 -0
  52. seleniumbase/undetected/cdp_driver/browser.py +829 -0
  53. seleniumbase/undetected/cdp_driver/cdp_util.py +458 -0
  54. seleniumbase/undetected/cdp_driver/config.py +334 -0
  55. seleniumbase/undetected/cdp_driver/connection.py +639 -0
  56. seleniumbase/undetected/cdp_driver/element.py +1168 -0
  57. seleniumbase/undetected/cdp_driver/tab.py +1323 -0
  58. seleniumbase/undetected/dprocess.py +4 -7
  59. seleniumbase/undetected/options.py +6 -8
  60. seleniumbase/undetected/patcher.py +11 -13
  61. seleniumbase/undetected/reactor.py +0 -1
  62. seleniumbase/undetected/webelement.py +16 -3
  63. {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/LICENSE +1 -1
  64. {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/METADATA +299 -252
  65. {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/RECORD +68 -70
  66. {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/WHEEL +1 -1
  67. sbase/ReadMe.txt +0 -2
  68. seleniumbase/ReadMe.md +0 -25
  69. seleniumbase/common/ReadMe.md +0 -71
  70. seleniumbase/console_scripts/ReadMe.md +0 -731
  71. seleniumbase/drivers/ReadMe.md +0 -27
  72. seleniumbase/extensions/ReadMe.md +0 -12
  73. seleniumbase/masterqa/ReadMe.md +0 -61
  74. seleniumbase/resources/ReadMe.md +0 -31
  75. seleniumbase/resources/favicon.ico +0 -0
  76. seleniumbase/utilities/selenium_grid/ReadMe.md +0 -84
  77. seleniumbase/utilities/selenium_ide/ReadMe.md +0 -111
  78. {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/entry_points.txt +0 -0
  79. {seleniumbase-4.24.10.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"):