seleniumbase 4.24.11__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 (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
@@ -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
+ )