seleniumbase 4.24.10__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 (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
@@ -0,0 +1,334 @@
1
+ import logging
2
+ import os
3
+ import pathlib
4
+ import secrets
5
+ import sys
6
+ import tempfile
7
+ import zipfile
8
+ from seleniumbase.config import settings
9
+ from typing import Union, List, Optional
10
+
11
+ __all__ = [
12
+ "Config",
13
+ "find_chrome_executable",
14
+ "temp_profile_dir",
15
+ "is_root",
16
+ "is_posix",
17
+ "PathLike",
18
+ ]
19
+
20
+ logger = logging.getLogger(__name__)
21
+ is_posix = sys.platform.startswith(("darwin", "cygwin", "linux", "linux2"))
22
+
23
+ PathLike = Union[str, pathlib.Path]
24
+ AUTO = None
25
+
26
+
27
+ class Config:
28
+ """Config object"""
29
+
30
+ def __init__(
31
+ self,
32
+ user_data_dir: Optional[PathLike] = AUTO,
33
+ headless: Optional[bool] = False,
34
+ incognito: Optional[bool] = False,
35
+ guest: Optional[bool] = False,
36
+ browser_executable_path: Optional[PathLike] = AUTO,
37
+ browser_args: Optional[List[str]] = AUTO,
38
+ sandbox: Optional[bool] = True,
39
+ lang: Optional[str] = "en-US",
40
+ host: str = AUTO,
41
+ port: int = AUTO,
42
+ expert: bool = AUTO,
43
+ **kwargs: dict,
44
+ ):
45
+ """
46
+ Creates a config object.
47
+ Can be called without any arguments to generate a best-practice config,
48
+ which is recommended.
49
+ Calling the object, eg: myconfig(), returns the list of arguments which
50
+ are provided to the browser.
51
+ Additional args can be added using the :py:obj:`~add_argument method`.
52
+ Instances of this class are usually not instantiated by end users.
53
+ :param user_data_dir: the data directory to use
54
+ :param headless: set to True for headless mode
55
+ :param browser_executable_path:
56
+ Specify browser executable, instead of using autodetect.
57
+ :param browser_args: Forwarded to browser executable.
58
+ Eg: ["--some-chromeparam=somevalue", "some-other-param=someval"]
59
+ :param sandbox: disables sandbox
60
+ :param autodiscover_targets: use autodiscovery of targets
61
+ :param lang:
62
+ Language string to use other than the default "en-US,en;q=0.9"
63
+ :param expert: When set to True, "expert" mode is enabled.
64
+ This adds: --disable-web-security --disable-site-isolation-trials,
65
+ as well as some scripts and patching useful for debugging.
66
+ (For example, ensuring shadow-root is always in "open" mode.)
67
+ :param kwargs:
68
+ :type user_data_dir: PathLike
69
+ :type headless: bool
70
+ :type browser_executable_path: PathLike
71
+ :type browser_args: list[str]
72
+ :type sandbox: bool
73
+ :type lang: str
74
+ :type kwargs: dict
75
+ """
76
+ if not browser_args:
77
+ browser_args = []
78
+ if not user_data_dir:
79
+ self._user_data_dir = temp_profile_dir()
80
+ self._custom_data_dir = False
81
+ else:
82
+ self.user_data_dir = user_data_dir
83
+ if not browser_executable_path:
84
+ browser_executable_path = find_chrome_executable()
85
+ self._browser_args = browser_args
86
+ self.browser_executable_path = browser_executable_path
87
+ self.headless = headless
88
+ self.incognito = incognito
89
+ self.guest = guest
90
+ self.sandbox = sandbox
91
+ self.host = host
92
+ self.port = port
93
+ self.expert = expert
94
+ self._extensions = []
95
+ # When using posix-ish operating system and running as root,
96
+ # you must use no_sandbox=True
97
+ if is_posix and is_root() and sandbox:
98
+ logger.info("Detected root usage, auto-disabling sandbox mode.")
99
+ self.sandbox = False
100
+ self.autodiscover_targets = True
101
+ self.lang = lang
102
+ # Other keyword args will be accessible by attribute
103
+ self.__dict__.update(kwargs)
104
+ super().__init__()
105
+ start_width = settings.CHROME_START_WIDTH
106
+ start_height = settings.CHROME_START_HEIGHT
107
+ start_x = settings.WINDOW_START_X
108
+ start_y = settings.WINDOW_START_Y
109
+ self._default_browser_args = [
110
+ "--window-size=%s,%s" % (start_width, start_height),
111
+ "--window-position=%s,%s" % (start_x, start_y),
112
+ "--remote-allow-origins=*",
113
+ "--no-first-run",
114
+ "--no-service-autorun",
115
+ "--disable-auto-reload",
116
+ "--no-default-browser-check",
117
+ "--homepage=about:blank",
118
+ "--no-pings",
119
+ "--wm-window-animations-disabled",
120
+ "--animation-duration-scale=0",
121
+ "--enable-privacy-sandbox-ads-apis",
122
+ "--safebrowsing-disable-download-protection",
123
+ '--simulate-outdated-no-au="Tue, 31 Dec 2099 23:59:59 GMT"',
124
+ "--password-store=basic",
125
+ "--deny-permission-prompts",
126
+ "--disable-infobars",
127
+ "--disable-breakpad",
128
+ "--disable-prompt-on-repost",
129
+ "--disable-password-generation",
130
+ "--disable-ipc-flooding-protection",
131
+ "--disable-background-timer-throttling",
132
+ "--disable-search-engine-choice-screen",
133
+ "--disable-backgrounding-occluded-windows",
134
+ "--disable-client-side-phishing-detection",
135
+ "--disable-top-sites",
136
+ "--disable-translate",
137
+ "--disable-renderer-backgrounding",
138
+ "--disable-background-networking",
139
+ "--disable-dev-shm-usage",
140
+ "--disable-features=IsolateOrigins,site-per-process,Translate,"
141
+ "InsecureDownloadWarnings,DownloadBubble,DownloadBubbleV2,"
142
+ "OptimizationTargetPrediction,OptimizationGuideModelDownloading,"
143
+ "SidePanelPinning,UserAgentClientHint,PrivacySandboxSettings4",
144
+ ]
145
+
146
+ @property
147
+ def browser_args(self):
148
+ return sorted(self._default_browser_args + self._browser_args)
149
+
150
+ @property
151
+ def user_data_dir(self):
152
+ return self._user_data_dir
153
+
154
+ @user_data_dir.setter
155
+ def user_data_dir(self, path: PathLike):
156
+ self._user_data_dir = str(path)
157
+ self._custom_data_dir = True
158
+
159
+ @property
160
+ def uses_custom_data_dir(self) -> bool:
161
+ return self._custom_data_dir
162
+
163
+ def add_extension(self, extension_path: PathLike):
164
+ """
165
+ Adds an extension to load. You can set the extension_path to a
166
+ folder (containing the manifest), or an extension zip file (.crx)
167
+ :param extension_path:
168
+ """
169
+ path = pathlib.Path(extension_path)
170
+ if not path.exists():
171
+ raise FileNotFoundError(
172
+ "Could not find anything here: %s" % str(path)
173
+ )
174
+ if path.is_file():
175
+ tf = tempfile.mkdtemp(
176
+ prefix="extension_", suffix=secrets.token_hex(4)
177
+ )
178
+ with zipfile.ZipFile(path, "r") as z:
179
+ z.extractall(tf)
180
+ self._extensions.append(tf)
181
+ elif path.is_dir():
182
+ for item in path.rglob("manifest.*"):
183
+ path = item.parent
184
+ self._extensions.append(path)
185
+
186
+ def __call__(self):
187
+ # The host and port will be added when starting the browser.
188
+ # By the time it starts, the port is probably already taken.
189
+ args = self._default_browser_args.copy()
190
+ args += ["--user-data-dir=%s" % self.user_data_dir]
191
+ args += ["--disable-features=IsolateOrigins,site-per-process"]
192
+ args += ["--disable-session-crashed-bubble"]
193
+ if self.expert:
194
+ args += [
195
+ "--disable-web-security",
196
+ "--disable-site-isolation-trials",
197
+ ]
198
+ if self._browser_args:
199
+ args.extend([arg for arg in self._browser_args if arg not in args])
200
+ if self.headless:
201
+ args.append("--headless=new")
202
+ if self.incognito:
203
+ args.append("--incognito")
204
+ if self.guest:
205
+ args.append("--guest")
206
+ if not self.sandbox:
207
+ args.append("--no-sandbox")
208
+ if self.host:
209
+ args.append("--remote-debugging-host=%s" % self.host)
210
+ if self.port:
211
+ args.append("--remote-debugging-port=%s" % self.port)
212
+ return args
213
+
214
+ def add_argument(self, arg: str):
215
+ if any(
216
+ x in arg.lower()
217
+ for x in [
218
+ "headless",
219
+ "data-dir",
220
+ "data_dir",
221
+ "no-sandbox",
222
+ "no_sandbox",
223
+ "lang",
224
+ ]
225
+ ):
226
+ raise ValueError(
227
+ '"%s" is not allowed. Please use one of the '
228
+ 'attributes of the Config object to set it.'
229
+ % arg
230
+ )
231
+ self._browser_args.append(arg)
232
+
233
+ def __repr__(self):
234
+ s = f"{self.__class__.__name__}"
235
+ for k, v in ({**self.__dict__, **self.__class__.__dict__}).items():
236
+ if k[0] == "_":
237
+ continue
238
+ if not v:
239
+ continue
240
+ if isinstance(v, property):
241
+ v = getattr(self, k)
242
+ if callable(v):
243
+ continue
244
+ s += f"\n\t{k} = {v}"
245
+ return s
246
+
247
+
248
+ def is_root():
249
+ """
250
+ Helper function to determine if the user is trying to launch chrome
251
+ under linux as root, which needs some alternative handling.
252
+ """
253
+ import ctypes
254
+ import os
255
+
256
+ try:
257
+ return os.getuid() == 0
258
+ except AttributeError:
259
+ return ctypes.windll.shell32.IsUserAnAdmin() != 0
260
+
261
+
262
+ def temp_profile_dir():
263
+ """Generate a temp dir (path)"""
264
+ path = os.path.normpath(tempfile.mkdtemp(prefix="uc_"))
265
+ return path
266
+
267
+
268
+ def find_chrome_executable(return_all=False):
269
+ """
270
+ Finds the chrome, beta, canary, chromium executable
271
+ and returns the disk path.
272
+ """
273
+ candidates = []
274
+ if is_posix:
275
+ for item in os.environ.get("PATH").split(os.pathsep):
276
+ for subitem in (
277
+ "google-chrome",
278
+ "chromium",
279
+ "chromium-browser",
280
+ "chrome",
281
+ "google-chrome-stable",
282
+ ):
283
+ candidates.append(os.sep.join((item, subitem)))
284
+ if "darwin" in sys.platform:
285
+ candidates += [
286
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
287
+ "/Applications/Chromium.app/Contents/MacOS/Chromium",
288
+ ]
289
+ else:
290
+ for item in map(
291
+ os.environ.get,
292
+ (
293
+ "PROGRAMFILES",
294
+ "PROGRAMFILES(X86)",
295
+ "LOCALAPPDATA",
296
+ "PROGRAMW6432",
297
+ ),
298
+ ):
299
+ if item is not None:
300
+ for subitem in (
301
+ "Google/Chrome/Application",
302
+ "Google/Chrome Beta/Application",
303
+ "Google/Chrome Canary/Application",
304
+ ):
305
+ candidates.append(
306
+ os.sep.join((item, subitem, "chrome.exe"))
307
+ )
308
+ rv = []
309
+ for candidate in candidates:
310
+ if os.path.exists(candidate) and os.access(candidate, os.X_OK):
311
+ logger.debug("%s is a valid candidate... " % candidate)
312
+ rv.append(candidate)
313
+ else:
314
+ logger.debug(
315
+ "%s is not a valid candidate because it doesn't exist "
316
+ "or isn't an executable."
317
+ % candidate
318
+ )
319
+ winner = None
320
+ if return_all and rv:
321
+ return rv
322
+ if rv and len(rv) > 1:
323
+ # Assuming the shortest path wins
324
+ winner = min(rv, key=lambda x: len(x))
325
+ elif len(rv) == 1:
326
+ winner = rv[0]
327
+ if winner:
328
+ return os.path.normpath(winner)
329
+ raise FileNotFoundError(
330
+ "Could not find a valid chrome browser binary. "
331
+ "Please make sure Chrome is installed. "
332
+ "Or use the keyword argument: "
333
+ "'browser_executable_path=/path/to/your/browser'."
334
+ )