seleniumbase 4.33.5__py3-none-any.whl → 4.33.6__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.
@@ -1,2 +1,2 @@
1
1
  # seleniumbase package
2
- __version__ = "4.33.5"
2
+ __version__ = "4.33.6"
@@ -97,26 +97,12 @@ def log_d(message):
97
97
  print(message)
98
98
 
99
99
 
100
- def make_writable(file_path):
101
- # Set permissions to: "If you can read it, you can write it."
102
- mode = os.stat(file_path).st_mode
103
- mode |= (mode & 0o444) >> 1 # copy R bits to W
104
- os.chmod(file_path, mode)
105
-
106
-
107
- def make_executable(file_path):
108
- # Set permissions to: "If you can read it, you can execute it."
109
- mode = os.stat(file_path).st_mode
110
- mode |= (mode & 0o444) >> 2 # copy R bits to X
111
- os.chmod(file_path, mode)
112
-
113
-
114
100
  def make_driver_executable_if_not(driver_path):
115
101
  # Verify driver has executable permissions. If not, add them.
116
102
  permissions = oct(os.stat(driver_path)[0])[-3:]
117
103
  if "4" in permissions or "6" in permissions:
118
104
  # We want at least a '5' or '7' to make sure it's executable
119
- make_executable(driver_path)
105
+ shared_utils.make_executable(driver_path)
120
106
 
121
107
 
122
108
  def extend_driver(driver):
@@ -566,6 +552,10 @@ def uc_open_with_cdp_mode(driver, url=None):
566
552
  for tab in driver.cdp_base.tabs[-1::-1]:
567
553
  if "chrome-extension://" not in str(tab):
568
554
  with gui_lock:
555
+ with suppress(Exception):
556
+ shared_utils.make_writable(
557
+ constants.MultiBrowser.PYAUTOGUILOCK
558
+ )
569
559
  loop.run_until_complete(tab.activate())
570
560
  break
571
561
 
@@ -580,11 +570,17 @@ def uc_open_with_cdp_mode(driver, url=None):
580
570
  if page_tab:
581
571
  loop.run_until_complete(page_tab.aopen())
582
572
  with gui_lock:
573
+ with suppress(Exception):
574
+ shared_utils.make_writable(
575
+ constants.MultiBrowser.PYAUTOGUILOCK
576
+ )
583
577
  loop.run_until_complete(page_tab.activate())
584
578
 
585
579
  loop.run_until_complete(driver.cdp_base.update_targets())
586
580
  page = loop.run_until_complete(driver.cdp_base.get(url))
587
581
  with gui_lock:
582
+ with suppress(Exception):
583
+ shared_utils.make_writable(constants.MultiBrowser.PYAUTOGUILOCK)
588
584
  loop.run_until_complete(page.activate())
589
585
  loop.run_until_complete(page.wait())
590
586
  if not safe_url:
@@ -883,17 +879,12 @@ def install_pyautogui_if_missing(driver):
883
879
  with pip_find_lock:
884
880
  pass
885
881
  except Exception:
886
- # Need write permissions
887
- with suppress(Exception):
888
- make_writable(constants.PipInstall.FINDLOCK)
889
- try:
890
- with pip_find_lock:
891
- pass
892
- except Exception:
893
- # Since missing permissions, skip the locks
894
- __install_pyautogui_if_missing()
895
- return
882
+ # Since missing permissions, skip the locks
883
+ __install_pyautogui_if_missing()
884
+ return
896
885
  with pip_find_lock: # Prevent issues with multiple processes
886
+ with suppress(Exception):
887
+ shared_utils.make_writable(constants.PipInstall.FINDLOCK)
897
888
  __install_pyautogui_if_missing()
898
889
 
899
890
 
@@ -1789,6 +1780,8 @@ def _add_chrome_proxy_extension(
1789
1780
  if zip_it:
1790
1781
  proxy_zip_lock = fasteners.InterProcessLock(PROXY_ZIP_LOCK)
1791
1782
  with proxy_zip_lock:
1783
+ with suppress(Exception):
1784
+ shared_utils.make_writable(PROXY_ZIP_LOCK)
1792
1785
  if multi_proxy:
1793
1786
  _set_proxy_filenames()
1794
1787
  if not os.path.exists(proxy_helper.PROXY_ZIP_PATH):
@@ -1800,6 +1793,8 @@ def _add_chrome_proxy_extension(
1800
1793
  else:
1801
1794
  proxy_dir_lock = fasteners.InterProcessLock(PROXY_DIR_LOCK)
1802
1795
  with proxy_dir_lock:
1796
+ with suppress(Exception):
1797
+ shared_utils.make_writable(PROXY_DIR_LOCK)
1803
1798
  if multi_proxy:
1804
1799
  _set_proxy_filenames()
1805
1800
  if not os.path.exists(proxy_helper.PROXY_DIR_PATH):
@@ -1825,6 +1820,8 @@ def is_using_uc(undetectable, browser_name):
1825
1820
  def _unzip_to_new_folder(zip_file, folder):
1826
1821
  proxy_dir_lock = fasteners.InterProcessLock(PROXY_DIR_LOCK)
1827
1822
  with proxy_dir_lock:
1823
+ with suppress(Exception):
1824
+ shared_utils.make_writable(PROXY_DIR_LOCK)
1828
1825
  if not os.path.exists(folder):
1829
1826
  import zipfile
1830
1827
  zip_ref = zipfile.ZipFile(zip_file, "r")
@@ -2934,6 +2931,8 @@ def get_remote_driver(
2934
2931
  constants.PipInstall.FINDLOCK
2935
2932
  )
2936
2933
  with pip_find_lock: # Prevent issues with multiple processes
2934
+ with suppress(Exception):
2935
+ shared_utils.make_writable(constants.PipInstall.FINDLOCK)
2937
2936
  try:
2938
2937
  from seleniumwire import webdriver
2939
2938
  import blinker
@@ -3371,6 +3370,8 @@ def get_local_driver(
3371
3370
  constants.PipInstall.FINDLOCK
3372
3371
  )
3373
3372
  with pip_find_lock: # Prevent issues with multiple processes
3373
+ with suppress(Exception):
3374
+ shared_utils.make_writable(constants.PipInstall.FINDLOCK)
3374
3375
  try:
3375
3376
  from seleniumwire import webdriver
3376
3377
  import blinker
@@ -3434,6 +3435,10 @@ def get_local_driver(
3434
3435
  constants.MultiBrowser.DRIVER_FIXING_LOCK
3435
3436
  )
3436
3437
  with geckodriver_fixing_lock:
3438
+ with suppress(Exception):
3439
+ shared_utils.make_writable(
3440
+ constants.MultiBrowser.DRIVER_FIXING_LOCK
3441
+ )
3437
3442
  if not geckodriver_on_path():
3438
3443
  sys_args = sys.argv # Save a copy of sys args
3439
3444
  log_d(
@@ -3736,6 +3741,10 @@ def get_local_driver(
3736
3741
  constants.MultiBrowser.DRIVER_FIXING_LOCK
3737
3742
  )
3738
3743
  with edgedriver_fixing_lock:
3744
+ with suppress(Exception):
3745
+ shared_utils.make_writable(
3746
+ constants.MultiBrowser.DRIVER_FIXING_LOCK
3747
+ )
3739
3748
  msg = "Microsoft Edge Driver not found."
3740
3749
  if edgedriver_upgrade_needed:
3741
3750
  msg = "Microsoft Edge Driver update needed."
@@ -4119,6 +4128,10 @@ def get_local_driver(
4119
4128
  constants.MultiBrowser.DRIVER_FIXING_LOCK
4120
4129
  )
4121
4130
  with edgedriver_fixing_lock:
4131
+ with suppress(Exception):
4132
+ shared_utils.make_writable(
4133
+ constants.MultiBrowser.DRIVER_FIXING_LOCK
4134
+ )
4122
4135
  with suppress(Exception):
4123
4136
  if not _was_driver_repaired():
4124
4137
  _repair_edgedriver(edge_version)
@@ -4501,6 +4514,10 @@ def get_local_driver(
4501
4514
  constants.MultiBrowser.DRIVER_FIXING_LOCK
4502
4515
  )
4503
4516
  with chromedriver_fixing_lock:
4517
+ with suppress(Exception):
4518
+ shared_utils.make_writable(
4519
+ constants.MultiBrowser.DRIVER_FIXING_LOCK
4520
+ )
4504
4521
  msg = "chromedriver update needed. Getting it now:"
4505
4522
  if not path_chromedriver:
4506
4523
  msg = "chromedriver not found. Getting it now:"
@@ -4592,6 +4609,10 @@ def get_local_driver(
4592
4609
  constants.MultiBrowser.DRIVER_FIXING_LOCK
4593
4610
  )
4594
4611
  with uc_lock: # Avoid multithreaded issues
4612
+ with suppress(Exception):
4613
+ shared_utils.make_writable(
4614
+ constants.MultiBrowser.DRIVER_FIXING_LOCK
4615
+ )
4595
4616
  if make_uc_driver_from_chromedriver:
4596
4617
  if os.path.exists(LOCAL_CHROMEDRIVER):
4597
4618
  with suppress(Exception):
@@ -4851,6 +4872,10 @@ def get_local_driver(
4851
4872
  if not os.path.exists(cf_lock_path):
4852
4873
  # Avoid multithreaded issues
4853
4874
  with cf_lock:
4875
+ with suppress(Exception):
4876
+ shared_utils.make_writable(
4877
+ cf_lock_path
4878
+ )
4854
4879
  # Install Python Certificates (MAC)
4855
4880
  os.system(
4856
4881
  r"bash /Applications/Python*/"
@@ -4994,6 +5019,10 @@ def get_local_driver(
4994
5019
  constants.MultiBrowser.DRIVER_FIXING_LOCK
4995
5020
  )
4996
5021
  with chromedriver_fixing_lock:
5022
+ with suppress(Exception):
5023
+ shared_utils.make_writable(
5024
+ constants.MultiBrowser.DRIVER_FIXING_LOCK
5025
+ )
4997
5026
  if not _was_driver_repaired():
4998
5027
  _repair_chromedriver(
4999
5028
  chrome_options, headless_options, mcv
@@ -5192,7 +5221,10 @@ def get_local_driver(
5192
5221
  chromedr_fixing_lock = fasteners.InterProcessLock(
5193
5222
  constants.MultiBrowser.DRIVER_FIXING_LOCK
5194
5223
  )
5224
+ D_F_L = constants.MultiBrowser.DRIVER_FIXING_LOCK
5195
5225
  with chromedr_fixing_lock:
5226
+ with suppress(Exception):
5227
+ shared_utils.make_writable(D_F_L)
5196
5228
  if not _was_driver_repaired():
5197
5229
  with suppress(Exception):
5198
5230
  _repair_chromedriver(
@@ -339,9 +339,10 @@ def log_skipped_test_data(test, test_logpath, driver, browser, reason):
339
339
  data_to_save.append(" * Skip Reason: %s" % reason)
340
340
  data_to_save.append("")
341
341
  file_path = os.path.join(test_logpath, "skip_reason.txt")
342
- log_file = codecs.open(file_path, "w+", encoding="utf-8")
343
- log_file.writelines("\r\n".join(data_to_save))
344
- log_file.close()
342
+ with suppress(Exception):
343
+ log_file = codecs.open(file_path, "w+", encoding="utf-8")
344
+ log_file.writelines("\r\n".join(data_to_save))
345
+ log_file.close()
345
346
 
346
347
 
347
348
  def log_page_source(test_logpath, driver, source=None):
@@ -368,9 +369,10 @@ def log_page_source(test_logpath, driver, source=None):
368
369
  if not os.path.exists(test_logpath):
369
370
  os.makedirs(test_logpath)
370
371
  html_file_path = os.path.join(test_logpath, html_file_name)
371
- html_file = codecs.open(html_file_path, "w+", encoding="utf-8")
372
- html_file.write(page_source)
373
- html_file.close()
372
+ with suppress(Exception):
373
+ html_file = codecs.open(html_file_path, "w+", encoding="utf-8")
374
+ html_file.write(page_source)
375
+ html_file.close()
374
376
 
375
377
 
376
378
  def get_test_id(test):
@@ -1019,6 +1019,10 @@ class CDPMethods():
1019
1019
  with suppress(Exception):
1020
1020
  self.loop.run_until_complete(self.page.evaluate(js_code))
1021
1021
 
1022
+ def __make_sure_pyautogui_lock_is_writable(self):
1023
+ with suppress(Exception):
1024
+ shared_utils.make_writable(constants.MultiBrowser.PYAUTOGUILOCK)
1025
+
1022
1026
  def __verify_pyautogui_has_a_headed_browser(self):
1023
1027
  """PyAutoGUI requires a headed browser so that it can
1024
1028
  focus on the correct element when performing actions."""
@@ -1039,6 +1043,8 @@ class CDPMethods():
1039
1043
  constants.PipInstall.FINDLOCK
1040
1044
  )
1041
1045
  with pip_find_lock: # Prevent issues with multiple processes
1046
+ with suppress(Exception):
1047
+ shared_utils.make_writable(constants.PipInstall.FINDLOCK)
1042
1048
  try:
1043
1049
  import pyautogui
1044
1050
  with suppress(Exception):
@@ -1124,6 +1130,7 @@ class CDPMethods():
1124
1130
  constants.MultiBrowser.PYAUTOGUILOCK
1125
1131
  )
1126
1132
  with gui_lock:
1133
+ self.__make_sure_pyautogui_lock_is_writable()
1127
1134
  pyautogui.press(key)
1128
1135
  time.sleep(0.044)
1129
1136
  self.__slow_mode_pause_if_set()
@@ -1137,6 +1144,7 @@ class CDPMethods():
1137
1144
  constants.MultiBrowser.PYAUTOGUILOCK
1138
1145
  )
1139
1146
  with gui_lock:
1147
+ self.__make_sure_pyautogui_lock_is_writable()
1140
1148
  for key in keys:
1141
1149
  pyautogui.press(key)
1142
1150
  time.sleep(0.044)
@@ -1151,6 +1159,7 @@ class CDPMethods():
1151
1159
  constants.MultiBrowser.PYAUTOGUILOCK
1152
1160
  )
1153
1161
  with gui_lock:
1162
+ self.__make_sure_pyautogui_lock_is_writable()
1154
1163
  pyautogui.write(text)
1155
1164
  self.__slow_mode_pause_if_set()
1156
1165
  self.loop.run_until_complete(self.page.wait())
@@ -1171,6 +1180,7 @@ class CDPMethods():
1171
1180
  constants.MultiBrowser.PYAUTOGUILOCK
1172
1181
  )
1173
1182
  with gui_lock: # Prevent issues with multiple processes
1183
+ self.__make_sure_pyautogui_lock_is_writable()
1174
1184
  pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
1175
1185
  if timeframe >= 0.25:
1176
1186
  time.sleep(0.056) # Wait if moving at human-speed
@@ -1191,6 +1201,7 @@ class CDPMethods():
1191
1201
  constants.MultiBrowser.PYAUTOGUILOCK
1192
1202
  )
1193
1203
  with gui_lock: # Prevent issues with multiple processes
1204
+ self.__make_sure_pyautogui_lock_is_writable()
1194
1205
  self.__install_pyautogui_if_missing()
1195
1206
  import pyautogui
1196
1207
  pyautogui = self.__get_configured_pyautogui(pyautogui)
@@ -1408,6 +1419,7 @@ class CDPMethods():
1408
1419
  constants.MultiBrowser.PYAUTOGUILOCK
1409
1420
  )
1410
1421
  with gui_lock:
1422
+ self.__make_sure_pyautogui_lock_is_writable()
1411
1423
  self.bring_active_window_to_front()
1412
1424
  self.gui_hover_element(hover_selector)
1413
1425
  time.sleep(0.15)
@@ -1,4 +1,5 @@
1
1
  import sys
2
+ import textwrap
2
3
  from seleniumbase.fixtures import constants
3
4
 
4
5
 
@@ -116,6 +117,7 @@ def get_report_style():
116
117
  }
117
118
  </style>"""
118
119
  )
120
+ style = textwrap.dedent(style)
119
121
  Saved.report_style = style
120
122
  return style
121
123
 
@@ -132,6 +134,7 @@ def get_bt_backdrop_style():
132
134
  box-shadow: 0 0 0 88422px rgba(0, 0, 0, 0.42);
133
135
  pointer-events: auto !important;
134
136
  }"""
137
+ bt_backdrop_style = textwrap.dedent(bt_backdrop_style)
135
138
  Saved.bt_backdrop_style = bt_backdrop_style
136
139
  return bt_backdrop_style
137
140
 
@@ -150,6 +153,7 @@ def get_dt_backdrop_style():
150
153
  button.driver-prev-btn.driver-disabled {
151
154
  visibility: hidden;
152
155
  }"""
156
+ dt_backdrop_style = textwrap.dedent(dt_backdrop_style)
153
157
  Saved.dt_backdrop_style = dt_backdrop_style
154
158
  return dt_backdrop_style
155
159
 
@@ -167,6 +171,7 @@ def get_messenger_style():
167
171
  box-shadow: 2px 2px 9px 4px rgba(32, 142, 120, 0.28),
168
172
  2px 2px 9px 4px rgba(200, 240, 80, 0.34) !important;
169
173
  }""" % font_family
174
+ messenger_style = textwrap.dedent(messenger_style)
170
175
  Saved.messenger_style = messenger_style
171
176
  return messenger_style
172
177
 
@@ -181,6 +186,7 @@ def get_sh_style_test():
181
186
  scrollTo: true
182
187
  }
183
188
  });"""
189
+ sh_style_test = textwrap.dedent(sh_style_test)
184
190
  Saved.sh_style_test = sh_style_test
185
191
  return sh_style_test
186
192
 
@@ -193,6 +199,7 @@ def get_hops_backdrop_style():
193
199
  .hopscotch-bubble-container {
194
200
  font-size: 110%;
195
201
  }"""
202
+ hops_backdrop_style = textwrap.dedent(hops_backdrop_style)
196
203
  Saved.hops_backdrop_style = hops_backdrop_style
197
204
  return hops_backdrop_style
198
205
 
@@ -227,6 +234,7 @@ def get_introjs_style():
227
234
  box-sizing: content-box;
228
235
  position: absolute;
229
236
  }"""
237
+ introjs_style = textwrap.dedent(introjs_style)
230
238
  Saved.introjs_style = introjs_style
231
239
  return introjs_style
232
240
 
@@ -261,6 +269,7 @@ def get_sh_backdrop_style():
261
269
  body.shepherd-active {
262
270
  pointer-events: none !important;
263
271
  }"""
272
+ sh_backdrop_style = textwrap.dedent(sh_backdrop_style)
264
273
  Saved.sh_backdrop_style = sh_backdrop_style
265
274
  return sh_backdrop_style
266
275
 
@@ -387,5 +396,6 @@ def get_pytest_style():
387
396
  .desc.active .sort-icon {
388
397
  border-top: 8px solid #999;
389
398
  }"""
399
+ pytest_style = textwrap.dedent(pytest_style)
390
400
  Saved.pytest_style = pytest_style
391
401
  return pytest_style
@@ -7042,6 +7042,8 @@ class BaseCase(unittest.TestCase):
7042
7042
  constants.PipInstall.FINDLOCK
7043
7043
  )
7044
7044
  with pip_find_lock:
7045
+ with suppress(Exception):
7046
+ shared_utils.make_writable(constants.PipInstall.FINDLOCK)
7045
7047
  if sys.version_info < (3, 9):
7046
7048
  # Fix bug in newer cryptography for Python 3.7 and 3.8:
7047
7049
  # "pyo3_runtime.PanicException: Python API call failed"
@@ -7292,6 +7294,8 @@ class BaseCase(unittest.TestCase):
7292
7294
  constants.PipInstall.FINDLOCK
7293
7295
  )
7294
7296
  with pip_find_lock:
7297
+ with suppress(Exception):
7298
+ shared_utils.make_writable(constants.PipInstall.FINDLOCK)
7295
7299
  try:
7296
7300
  from PIL import Image, ImageDraw
7297
7301
  except Exception:
@@ -7337,6 +7341,10 @@ class BaseCase(unittest.TestCase):
7337
7341
  constants.MultiBrowser.DOWNLOAD_FILE_LOCK
7338
7342
  )
7339
7343
  with download_file_lock:
7344
+ with suppress(Exception):
7345
+ shared_utils.make_writable(
7346
+ constants.MultiBrowser.DOWNLOAD_FILE_LOCK
7347
+ )
7340
7348
  if not destination_folder:
7341
7349
  destination_folder = constants.Files.DOWNLOADS_FOLDER
7342
7350
  if not os.path.exists(destination_folder):
@@ -7357,6 +7365,10 @@ class BaseCase(unittest.TestCase):
7357
7365
  constants.MultiBrowser.DOWNLOAD_FILE_LOCK
7358
7366
  )
7359
7367
  with download_file_lock:
7368
+ with suppress(Exception):
7369
+ shared_utils.make_writable(
7370
+ constants.MultiBrowser.DOWNLOAD_FILE_LOCK
7371
+ )
7360
7372
  if not destination_folder:
7361
7373
  destination_folder = constants.Files.DOWNLOADS_FOLDER
7362
7374
  if not os.path.exists(destination_folder):
@@ -7462,6 +7474,8 @@ class BaseCase(unittest.TestCase):
7462
7474
  constants.MultiBrowser.FILE_IO_LOCK
7463
7475
  )
7464
7476
  with file_io_lock:
7477
+ with suppress(Exception):
7478
+ shared_utils.make_writable(constants.MultiBrowser.FILE_IO_LOCK)
7465
7479
  with open(fpath, "r") as f:
7466
7480
  data = f.read().strip()
7467
7481
  return data
@@ -14057,19 +14071,12 @@ class BaseCase(unittest.TestCase):
14057
14071
  with pip_find_lock:
14058
14072
  pass
14059
14073
  except Exception:
14060
- # Need write permissions
14061
- with suppress(Exception):
14062
- mode = os.stat(constants.PipInstall.FINDLOCK).st_mode
14063
- mode |= (mode & 0o444) >> 1 # copy R bits to W
14064
- os.chmod(constants.PipInstall.FINDLOCK, mode)
14065
- try:
14066
- with pip_find_lock:
14067
- pass
14068
- except Exception:
14069
- # Since missing permissions, skip the locks
14070
- self.__activate_virtual_display()
14071
- return
14074
+ # Since missing permissions, skip the locks
14075
+ self.__activate_virtual_display()
14076
+ return
14072
14077
  with pip_find_lock: # Prevent issues with multiple processes
14078
+ with suppress(Exception):
14079
+ shared_utils.make_writable(constants.PipInstall.FINDLOCK)
14073
14080
  self.__activate_virtual_display()
14074
14081
 
14075
14082
  def __ad_block_as_needed(self):
@@ -15091,6 +15098,10 @@ class BaseCase(unittest.TestCase):
15091
15098
  if self.dashboard:
15092
15099
  if self._multithreaded:
15093
15100
  with self.dash_lock:
15101
+ with suppress(Exception):
15102
+ shared_utils.make_writable(
15103
+ constants.Dashboard.LOCKFILE
15104
+ )
15094
15105
  if not self._dash_initialized:
15095
15106
  sb_config._dashboard_initialized = True
15096
15107
  self._dash_initialized = True
@@ -15650,6 +15661,8 @@ class BaseCase(unittest.TestCase):
15650
15661
  constants.Dashboard.LOCKFILE
15651
15662
  )
15652
15663
  with self.dash_lock:
15664
+ with suppress(Exception):
15665
+ shared_utils.make_writable(constants.Dashboard.LOCKFILE)
15653
15666
  self.__process_dashboard(has_exception, init)
15654
15667
  else:
15655
15668
  self.__process_dashboard(has_exception, init)
@@ -16419,6 +16432,10 @@ class BaseCase(unittest.TestCase):
16419
16432
  if self.dashboard:
16420
16433
  if self._multithreaded:
16421
16434
  with self.dash_lock:
16435
+ with suppress(Exception):
16436
+ shared_utils.make_writable(
16437
+ constants.Dashboard.LOCKFILE
16438
+ )
16422
16439
  self.__process_dashboard(has_exception)
16423
16440
  else:
16424
16441
  self.__process_dashboard(has_exception)
@@ -128,6 +128,20 @@ def is_chrome_130_or_newer(self, binary_location=None):
128
128
  return False
129
129
 
130
130
 
131
+ def make_writable(file_path):
132
+ # Set permissions to: "If you can read it, you can write it."
133
+ mode = os.stat(file_path).st_mode
134
+ mode |= (mode & 0o444) >> 1 # copy R bits to W
135
+ os.chmod(file_path, mode)
136
+
137
+
138
+ def make_executable(file_path):
139
+ # Set permissions to: "If you can read it, you can execute it."
140
+ mode = os.stat(file_path).st_mode
141
+ mode |= (mode & 0o444) >> 2 # copy R bits to X
142
+ os.chmod(file_path, mode)
143
+
144
+
131
145
  def format_exc(exception, message):
132
146
  """Formats an exception message to make the output cleaner."""
133
147
  from selenium.common.exceptions import ElementNotVisibleException
@@ -2209,6 +2209,20 @@ def _perform_pytest_unconfigure_(config):
2209
2209
  f.write(the_html_r) # Finalize the HTML report
2210
2210
  with open(html_report_path_copy, "w", encoding="utf-8") as f:
2211
2211
  f.write(the_html_r) # Finalize the HTML report
2212
+ assets_style = "./assets/style.css"
2213
+ if os.path.exists(assets_style):
2214
+ html_style = None
2215
+ with open(assets_style, "r", encoding="utf-8") as f:
2216
+ html_style = f.read()
2217
+ if html_style:
2218
+ html_style = html_style.replace("top: -50px;", "top: 2px;")
2219
+ html_style = html_style.replace("+ 50px)", "+ 40px)")
2220
+ html_style = html_style.replace("ht: 240px;", "ht: 228px;")
2221
+ html_style = html_style.replace(
2222
+ "- 80px);", "- 80px);\n margin-bottom: -42px;"
2223
+ )
2224
+ with open(assets_style, "w", encoding="utf-8") as f:
2225
+ f.write(html_style)
2212
2226
  # Done with "pytest_unconfigure" unless using the Dashboard
2213
2227
  return
2214
2228
  stamp = ""
@@ -2290,6 +2304,20 @@ def _perform_pytest_unconfigure_(config):
2290
2304
  )
2291
2305
  with open(dashboard_path, "w", encoding="utf-8") as f:
2292
2306
  f.write(the_html_d) # Finalize the dashboard
2307
+ assets_style = "./assets/style.css"
2308
+ if os.path.exists(assets_style):
2309
+ html_style = None
2310
+ with open(assets_style, "r", encoding="utf-8") as f:
2311
+ html_style = f.read()
2312
+ if html_style:
2313
+ html_style = html_style.replace("top: -50px;", "top: 2px;")
2314
+ html_style = html_style.replace("+ 50px)", "+ 40px)")
2315
+ html_style = html_style.replace("ht: 240px;", "ht: 228px;")
2316
+ html_style = html_style.replace(
2317
+ "- 80px);", "- 80px);\n margin-bottom: -42px;"
2318
+ )
2319
+ with open(assets_style, "w", encoding="utf-8") as f:
2320
+ f.write(html_style)
2293
2321
  # Part 2: Appending a pytest html report with dashboard data
2294
2322
  html_report_path = None
2295
2323
  if sb_config._html_report_name:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: seleniumbase
3
- Version: 4.33.5
3
+ Version: 4.33.6
4
4
  Summary: A complete web automation framework for end-to-end testing.
5
5
  Home-page: https://github.com/seleniumbase/SeleniumBase
6
6
  Author: Michael Mintz
@@ -126,7 +126,7 @@ Requires-Dist: allure-python-commons>=2.13.5; extra == "allure"
126
126
  Requires-Dist: allure-behave>=2.13.5; extra == "allure"
127
127
  Provides-Extra: coverage
128
128
  Requires-Dist: coverage>=7.6.1; python_version < "3.9" and extra == "coverage"
129
- Requires-Dist: coverage>=7.6.8; python_version >= "3.9" and extra == "coverage"
129
+ Requires-Dist: coverage>=7.6.9; python_version >= "3.9" and extra == "coverage"
130
130
  Requires-Dist: pytest-cov>=5.0.0; python_version < "3.9" and extra == "coverage"
131
131
  Requires-Dist: pytest-cov>=6.0.0; python_version >= "3.9" and extra == "coverage"
132
132
  Provides-Extra: flake8
@@ -3,7 +3,7 @@ sbase/__main__.py,sha256=G0bVB1-DM4PGwQ1KyOupaWCs4ePbChZNNWuX2htim5U,647
3
3
  sbase/steps.py,sha256=_WvAjydKqZfTdnZW9LPKkRty-g-lfdUPmLqnZj6ulcs,43013
4
4
  seleniumbase/__init__.py,sha256=OtJh8nGKL4xtZpw8KPqmn7Q6R-86t4cWUDyVF5MbMTo,2398
5
5
  seleniumbase/__main__.py,sha256=dn1p6dgCchmcH1zzTzzQvFwwdQQqnTGH6ULV9m4hv24,654
6
- seleniumbase/__version__.py,sha256=0yzphBzPKyJTvl0mwJ0ISMXG0RNjbnOoBiyWcsdGWqw,46
6
+ seleniumbase/__version__.py,sha256=tGf6JE86qsdvGT3Hg89rYziT4htXliGRqhNNRUHlu7Y,46
7
7
  seleniumbase/behave/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  seleniumbase/behave/behave_helper.py,sha256=elkl8P9eLulRAioLstE9baYNM9N_PHBmAOcajX-pH_Y,24198
9
9
  seleniumbase/behave/behave_sb.py,sha256=-hza7Nx2U41mSObYiPMi48v3JlPh3sJO3yzP0kqZ1Gk,59174
@@ -36,7 +36,7 @@ seleniumbase/console_scripts/sb_print.py,sha256=tNy-bMDgwHJO3bZxMpmo9weSE8uhbH0C
36
36
  seleniumbase/console_scripts/sb_recorder.py,sha256=fnHb5-kh11Hit-E9Ha-e4QXzqLcZvtij6mb5qNd4B1Q,11032
37
37
  seleniumbase/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  seleniumbase/core/application_manager.py,sha256=e_0sjtI8cjY5BNyZj1QBR0j6_oCScxGmSXYEpcYwuZE,576
39
- seleniumbase/core/browser_launcher.py,sha256=AX1kLcURKVPcZPYG30PSB1Q49revm-9PA_aelPP4Hok,221596
39
+ seleniumbase/core/browser_launcher.py,sha256=D_bfBkZsBAq5-XlI49CCdazydYHccuFJy0tPPAE3lOE,223704
40
40
  seleniumbase/core/capabilities_parser.py,sha256=meIS2uHapTCq2ldfNAToC7r0cKmZDRXuYNKExM1GHDY,6038
41
41
  seleniumbase/core/colored_traceback.py,sha256=DrRWfg7XEnKcgY59Xj7Jdk09H-XqHYBSUpB-DiZt6iY,2020
42
42
  seleniumbase/core/create_db_tables.sql,sha256=VWPtrdiW_HQ6yETHjqTu-VIrTwvd8I8o1NfBeaVSHpU,972
@@ -44,17 +44,17 @@ seleniumbase/core/detect_b_ver.py,sha256=RxeGRMbBUTMrXh5KsS1P1SH7eEKYbzL1vQw1gTd
44
44
  seleniumbase/core/download_helper.py,sha256=qSR54kQISucF4RQaLCOuuerSu6DR41juGi_30HVvWYY,2943
45
45
  seleniumbase/core/encoded_images.py,sha256=rDKJ4cNJSuKiRcFViYU7bjyTS9_moI57gUPRXVg3u2k,14209
46
46
  seleniumbase/core/jqc_helper.py,sha256=2DDQr9Q2jSSZqFzX588jLlUM9oJvyrRWq2aORSIPUdI,10322
47
- seleniumbase/core/log_helper.py,sha256=T_nPPSRSjhqt6TTzVE6pN1owVvIeRBNF5pWK6sl4dMY,22609
47
+ seleniumbase/core/log_helper.py,sha256=mtZLuvpy3lZpXqQ1ekng11_P5sBkyiI7eXhJGm9j15I,22693
48
48
  seleniumbase/core/mysql.py,sha256=8Fzj3p5dhtDWfMpFqFYxpSwa9s1UltiHsWJ56_aPOqk,3993
49
49
  seleniumbase/core/proxy_helper.py,sha256=cXhu8ErK9Vjdm82RMaQj7hEq_yUWizSp6LyiD50Ieu4,8020
50
50
  seleniumbase/core/recorder_helper.py,sha256=fNGjbapXmEsht54x1o6Igk198QdnPxDDnjUOzQxNhNQ,25055
51
51
  seleniumbase/core/report_helper.py,sha256=AIl6Qava2yW1uSzbLpJBlPlYDz0KE-rVhogh8hsGWBo,12201
52
52
  seleniumbase/core/s3_manager.py,sha256=bkeI8I4y19ebWuQG1oEZV5qJbotC6eN8vin31OCNWJk,3521
53
- seleniumbase/core/sb_cdp.py,sha256=NyiooRREzeRQYITMiE9b0WwcH3-u8tMsy-cLJSnxerc,67644
53
+ seleniumbase/core/sb_cdp.py,sha256=wieKEfVZjbzX0AivHabtHPwsfmJLvg8Ks3RMO7Qa9KE,68274
54
54
  seleniumbase/core/sb_driver.py,sha256=NGa4adi8OAi2WFtFkEguXg3JCd1p-JuZweIpGNifEfU,13488
55
55
  seleniumbase/core/session_helper.py,sha256=s9zD3PVZEWVzG2h81cCUskbNWLfdjC_LwwQjKptHCak,558
56
56
  seleniumbase/core/settings_parser.py,sha256=KokVXpCiGZhJ-D4Bo-hizPz5r-iefzWoiTANu9zNaq4,7504
57
- seleniumbase/core/style_sheet.py,sha256=tPpJ1xl6Kuw425Z-3Y0OgVRLGXk_ciBDREZjXk_NuPE,11395
57
+ seleniumbase/core/style_sheet.py,sha256=QsfTBtgedfM3uTqgxtd53bhq202p9fwLMbFl9mPZgVg,11892
58
58
  seleniumbase/core/testcase_manager.py,sha256=TblCfo8Zfap1Bayip-qTu9gqT-KALSwXAX4awBpnEHg,4633
59
59
  seleniumbase/core/tour_helper.py,sha256=kj2cz-DGKlw9SX3tWnVp-snpk6Flvqj81-xmKdKDtg0,42555
60
60
  seleniumbase/core/visual_helper.py,sha256=Dj5iJKw-bT_3e6KDqMf0sJi7xs_D96yqLcNc8fqhrjI,3408
@@ -65,14 +65,14 @@ seleniumbase/extensions/disable_csp.zip,sha256=YMifIIgEBiLrEFrS1sfW4Exh4br1V4oK1
65
65
  seleniumbase/extensions/recorder.zip,sha256=OOyzF-Ize2cSRu1CqhzSAq5vusI9hqLLd2OIApUHesI,11918
66
66
  seleniumbase/extensions/sbase_ext.zip,sha256=3s1N8zrVaMz8RQEOIoBzC3KDjtmHwVZRvVsX25Odr_s,8175
67
67
  seleniumbase/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
- seleniumbase/fixtures/base_case.py,sha256=XsqsffZcEJfnA323DfgrFy-nRKIsRJ6r6ebylELaiLo,717662
68
+ seleniumbase/fixtures/base_case.py,sha256=HyRCsvOPN3E3tBOOonK0698IRWd-XaxNEMcciLnj8OI,718550
69
69
  seleniumbase/fixtures/constants.py,sha256=e1LppavlrAcI4XBJMq7u5j8SffaQ7SPQps1y0YvZYfY,13649
70
70
  seleniumbase/fixtures/css_to_xpath.py,sha256=9ouDB1xl4MJ2os6JOgTIAyHKOQfuxtxvXC3O5hSnEKA,1954
71
71
  seleniumbase/fixtures/errors.py,sha256=KyxuEVx_e3MPhVrJfNIa_3ltMpbCFxfy_jxK8RFNTns,555
72
72
  seleniumbase/fixtures/js_utils.py,sha256=t-hqdd75O6Kfe6y5U8986gvZGATpPfDiDnIqeZZodgw,51435
73
73
  seleniumbase/fixtures/page_actions.py,sha256=dbp63c-7asYZyd8aOu57Y3dxQQozp_VJsP5h74s1kBA,66552
74
74
  seleniumbase/fixtures/page_utils.py,sha256=5m7iXpikLs80TJoRO6_gEfXE1AKeQgcH1aFbR8o1C9A,12034
75
- seleniumbase/fixtures/shared_utils.py,sha256=WbPb15IvIWzRtMInKG8DUzJ26UZU-PixdOwTCjXQirU,7545
75
+ seleniumbase/fixtures/shared_utils.py,sha256=uDwq23NWl3iL6uID16sv93bY8CjaMfItXBjLwjRr2tw,7985
76
76
  seleniumbase/fixtures/unittest_helper.py,sha256=sfZ92rZeBAn_sF_yQ3I6_I7h3lyU5-cV_UMegBNoEm8,1294
77
77
  seleniumbase/fixtures/words.py,sha256=FOA4mAYvl3EPVpBTvgvK6YwCL8BdlRCmed685kEe7Vg,7827
78
78
  seleniumbase/fixtures/xpath_to_css.py,sha256=lML56k656fElXJ4NJF07r35FjctrbgQkXUotNk7A-as,8876
@@ -88,7 +88,7 @@ seleniumbase/plugins/basic_test_info.py,sha256=8ov6n417gPbqqvrlT4zrch7l2XcRt-GF2
88
88
  seleniumbase/plugins/db_reporting_plugin.py,sha256=En09qUCoojrk9-vbcnsoHdSELoGmag2GDIyu3jTiJas,7331
89
89
  seleniumbase/plugins/driver_manager.py,sha256=s20s0pJYaNrG0WNwyIC04oUMRVFjtm6V_nS1-EvFm7g,34492
90
90
  seleniumbase/plugins/page_source.py,sha256=loTnXxOj4kxEukuTZEiGyvKBhY3KDVDMnNlHHheTBDE,1889
91
- seleniumbase/plugins/pytest_plugin.py,sha256=p8KTnx-xMuo2uLU-pXBj0d0EJYE_9Eb9jMeHC-zwyw8,102988
91
+ seleniumbase/plugins/pytest_plugin.py,sha256=v95Ovdwd1-Kqhf05BkDtC_YfF7_cF5v9WDnpsxT7frg,104506
92
92
  seleniumbase/plugins/s3_logging_plugin.py,sha256=WDfertQgGOW_SRJpFMaekYD6vBVW9VO62POtXXy2HCM,2319
93
93
  seleniumbase/plugins/sb_manager.py,sha256=qCf6RAkAfziLTGgiJvB3V416RxWoTbRLm9wc-KsB8g8,54419
94
94
  seleniumbase/plugins/screen_shots.py,sha256=1hrXw-hzuZ1BR6Yh7AyWX2ABnvnP73-RCbwdz958gj4,1127
@@ -135,9 +135,9 @@ seleniumbase/utilities/selenium_grid/start-grid-hub.bat,sha256=Ftq-GrAKRYH2ssDPr
135
135
  seleniumbase/utilities/selenium_grid/start-grid-hub.sh,sha256=KADv0RUHONLL2_I443QFK8PryBpDmKn5Gy0s4o0vDSM,106
136
136
  seleniumbase/utilities/selenium_ide/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
137
  seleniumbase/utilities/selenium_ide/convert_ide.py,sha256=pZFnqEJQEKZPyNFjkLD29s2HPQgCrWW9XJWpCPhWOoM,31691
138
- seleniumbase-4.33.5.dist-info/LICENSE,sha256=odSYtWibXBnQ1gBg6CnDZ82n8kLF_if5-2nbqnEyD8k,1085
139
- seleniumbase-4.33.5.dist-info/METADATA,sha256=D84rG0Bm0fkB2p5-CFUNlUUL8KvU5INS56CzgXjSVX4,86528
140
- seleniumbase-4.33.5.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
141
- seleniumbase-4.33.5.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
142
- seleniumbase-4.33.5.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
143
- seleniumbase-4.33.5.dist-info/RECORD,,
138
+ seleniumbase-4.33.6.dist-info/LICENSE,sha256=odSYtWibXBnQ1gBg6CnDZ82n8kLF_if5-2nbqnEyD8k,1085
139
+ seleniumbase-4.33.6.dist-info/METADATA,sha256=U6U9MYVrwKt5UAQvZLghzL2kEkNnTEadmP6TZZrMzvI,86528
140
+ seleniumbase-4.33.6.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
141
+ seleniumbase-4.33.6.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
142
+ seleniumbase-4.33.6.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
143
+ seleniumbase-4.33.6.dist-info/RECORD,,