Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/py/selenium/webdriver/common/options.py
4007 views
1
# Licensed to the Software Freedom Conservancy (SFC) under one
2
# or more contributor license agreements. See the NOTICE file
3
# distributed with this work for additional information
4
# regarding copyright ownership. The SFC licenses this file
5
# to you under the Apache License, Version 2.0 (the
6
# "License"); you may not use this file except in compliance
7
# with the License. You may obtain a copy of the License at
8
#
9
# http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing,
12
# software distributed under the License is distributed on an
13
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
# KIND, either express or implied. See the License for the
15
# specific language governing permissions and limitations
16
# under the License.
17
18
import warnings
19
from abc import ABCMeta, abstractmethod
20
from enum import Enum
21
22
from selenium.common.exceptions import InvalidArgumentException
23
from selenium.webdriver.common.proxy import Proxy
24
25
26
class PageLoadStrategy(str, Enum):
27
"""Enum of possible page load strategies.
28
29
Selenium support following strategies:
30
* normal (default) - waits for all resources to download
31
* eager - DOM access is ready, but other resources like images may still be loading
32
* none - does not block `WebDriver` at all
33
34
Docs: https://www.selenium.dev/documentation/webdriver/drivers/options/#pageloadstrategy.
35
"""
36
37
normal = "normal"
38
eager = "eager"
39
none = "none"
40
41
42
class _BaseOptionsDescriptor:
43
def __init__(self, name):
44
self.name = name
45
46
def __get__(self, obj, cls):
47
if self.name == "enableBidi":
48
# whether BiDi is or will be enabled
49
value = obj._caps.get("webSocketUrl")
50
return value is True or isinstance(value, str)
51
if self.name == "webSocketUrl":
52
# Return socket url or None if not created yet
53
value = obj._caps.get(self.name)
54
return None if not isinstance(value, str) else value
55
if self.name in ("acceptInsecureCerts", "strictFileInteractability", "setWindowRect", "se:downloadsEnabled"):
56
return obj._caps.get(self.name, False)
57
return obj._caps.get(self.name)
58
59
def __set__(self, obj, value):
60
if self.name == "enableBidi":
61
obj.set_capability("webSocketUrl", value)
62
else:
63
obj.set_capability(self.name, value)
64
65
66
class _PageLoadStrategyDescriptor:
67
"""Determines the point at which a navigation command is returned.
68
69
See:
70
- https://w3c.github.io/webdriver/#dfn-table-of-page-load-strategies.
71
72
Args:
73
strategy: the strategy corresponding to a document readiness state
74
"""
75
76
def __init__(self, name):
77
self.name = name
78
79
def __get__(self, obj, cls):
80
return obj._caps.get(self.name)
81
82
def __set__(self, obj, value):
83
if value in ("normal", "eager", "none"):
84
obj.set_capability(self.name, value)
85
else:
86
raise ValueError("Strategy can only be one of the following: normal, eager, none")
87
88
89
class _UnHandledPromptBehaviorDescriptor:
90
"""How the driver should respond when an alert is present and the command sent is not handling the alert.
91
92
See:
93
- https://w3c.github.io/webdriver/#dfn-table-of-page-load-strategies:
94
95
Args:
96
behavior: behavior to use when an alert is encountered
97
98
Returns:
99
Values for implicit timeout, pageLoad timeout and script timeout if set (in milliseconds)
100
"""
101
102
def __init__(self, name):
103
self.name = name
104
105
def __get__(self, obj, cls):
106
return obj._caps.get(self.name)
107
108
def __set__(self, obj, value):
109
if value in ("dismiss", "accept", "dismiss and notify", "accept and notify", "ignore"):
110
obj.set_capability(self.name, value)
111
else:
112
raise ValueError(
113
"Behavior can only be one of the following: dismiss, accept, dismiss and notify, "
114
"accept and notify, ignore"
115
)
116
117
118
class _TimeoutsDescriptor:
119
"""How long the driver should wait for actions to complete before returning an error.
120
121
See:
122
- https://w3c.github.io/webdriver/#timeouts
123
124
Args:
125
timeouts: values in milliseconds for implicit wait, page load and script timeout
126
127
Returns:
128
Values for implicit timeout, pageLoad timeout and script timeout if set (in milliseconds)
129
"""
130
131
def __init__(self, name):
132
self.name = name
133
134
def __get__(self, obj, cls):
135
return obj._caps.get(self.name)
136
137
def __set__(self, obj, value):
138
if all(x in ("implicit", "pageLoad", "script") for x in value.keys()):
139
obj.set_capability(self.name, value)
140
else:
141
raise ValueError("Timeout keys can only be one of the following: implicit, pageLoad, script")
142
143
144
class _ProxyDescriptor:
145
"""Descriptor for proxy property access.
146
147
Returns:
148
Proxy if set, otherwise None.
149
"""
150
151
def __init__(self, name):
152
self.name = name
153
154
def __get__(self, obj, cls):
155
return obj._proxy
156
157
def __set__(self, obj, value):
158
if not isinstance(value, Proxy):
159
raise InvalidArgumentException("Only Proxy objects can be passed in.")
160
obj._proxy = value
161
obj._caps[self.name] = value.to_capabilities()
162
163
164
class BaseOptions(metaclass=ABCMeta):
165
"""Base class for individual browser options."""
166
167
browser_version = _BaseOptionsDescriptor("browserVersion")
168
"""Gets and Sets the version of the browser.
169
170
Usage:
171
- Get: `self.browser_version`
172
- Set: `self.browser_version = value`
173
174
Args:
175
value: str
176
177
Returns:
178
str when getting, None when setting.
179
"""
180
181
platform_name = _BaseOptionsDescriptor("platformName")
182
"""Gets and Sets name of the platform.
183
184
Usage:
185
- Get: `self.platform_name`
186
- Set: `self.platform_name = value`
187
188
Args:
189
value: str
190
191
Returns:
192
str when getting, None when setting.
193
"""
194
195
accept_insecure_certs = _BaseOptionsDescriptor("acceptInsecureCerts")
196
"""Gets and Set whether the session accepts insecure certificates.
197
198
Usage:
199
- Get: `self.accept_insecure_certs`
200
- Set: `self.accept_insecure_certs = value`
201
202
Args:
203
value: bool
204
205
Returns:
206
bool when getting, None when setting.
207
"""
208
209
strict_file_interactability = _BaseOptionsDescriptor("strictFileInteractability")
210
"""Gets and Sets whether session is about file interactability.
211
212
Usage:
213
- Get: `self.strict_file_interactability`
214
- Set: `self.strict_file_interactability = value`
215
216
Args:
217
value: bool
218
219
Returns:
220
bool when getting, None when setting.
221
"""
222
223
set_window_rect = _BaseOptionsDescriptor("setWindowRect")
224
"""Gets and Sets window size and position.
225
226
Usage:
227
- Get: `self.set_window_rect`
228
- Set: `self.set_window_rect = value`
229
230
Args:
231
value: bool
232
233
Returns:
234
bool when getting, None when setting.
235
"""
236
237
enable_bidi = _BaseOptionsDescriptor("enableBidi")
238
"""Gets and Set whether the session has WebDriverBiDi enabled.
239
240
Usage:
241
- Get: `self.enable_bidi`
242
- Set: `self.enable_bidi = value`
243
244
Args:
245
value: bool
246
247
Returns:
248
bool when getting, None when setting.
249
"""
250
251
page_load_strategy = _PageLoadStrategyDescriptor("pageLoadStrategy")
252
"""Gets and Sets page load strategy, the default is "normal".
253
254
Usage:
255
- Get: `self.page_load_strategy`
256
- Set: `self.page_load_strategy = value`
257
258
Args:
259
value: str
260
261
Returns:
262
str when getting, None when setting.
263
"""
264
265
unhandled_prompt_behavior = _UnHandledPromptBehaviorDescriptor("unhandledPromptBehavior")
266
"""Gets and Sets unhandled prompt behavior, the default is "dismiss and notify".
267
268
Usage:
269
- Get: `self.unhandled_prompt_behavior`
270
- Set: `self.unhandled_prompt_behavior = value`
271
272
Args:
273
value: str
274
275
Returns:
276
str when getting, None when setting.
277
"""
278
279
timeouts = _TimeoutsDescriptor("timeouts")
280
"""Gets and Sets implicit timeout, pageLoad timeout and script timeout if set (in milliseconds).
281
282
Usage:
283
- Get: `self.timeouts`
284
- Set: `self.timeouts = value`
285
286
Args:
287
value: dict
288
289
Returns:
290
dict when getting, None when setting.
291
"""
292
293
proxy = _ProxyDescriptor("proxy")
294
"""Sets and Gets Proxy.
295
296
Usage:
297
- Get: `self.proxy`
298
- Set: `self.proxy = value`
299
300
Args:
301
value: Proxy
302
303
Returns:
304
Proxy when getting, None when setting.
305
"""
306
307
enable_downloads = _BaseOptionsDescriptor("se:downloadsEnabled")
308
"""Gets and Sets whether session can download files.
309
310
Usage:
311
- Get: `self.enable_downloads`
312
- Set: `self.enable_downloads = value`
313
314
Args:
315
value: bool
316
317
Returns:
318
bool when getting, None when setting.
319
"""
320
321
web_socket_url = _BaseOptionsDescriptor("webSocketUrl")
322
"""Gets and Sets WebSocket URL.
323
324
Usage:
325
- Get: `self.web_socket_url`
326
- Set: `self.web_socket_url = value`
327
328
Args:
329
value: str
330
331
Returns:
332
str when getting, None when setting.
333
"""
334
335
def __init__(self) -> None:
336
super().__init__()
337
self._caps = self.default_capabilities
338
self._proxy = None
339
self.set_capability("pageLoadStrategy", PageLoadStrategy.normal)
340
self.mobile_options: dict[str, str] | None = None
341
self._ignore_local_proxy = False
342
343
@property
344
def capabilities(self):
345
return self._caps
346
347
def set_capability(self, name, value) -> None:
348
"""Sets a capability."""
349
self._caps[name] = value
350
351
def enable_mobile(
352
self,
353
android_package: str | None = None,
354
android_activity: str | None = None,
355
device_serial: str | None = None,
356
) -> None:
357
"""Enables mobile browser use for browsers that support it.
358
359
Args:
360
android_package: The name of the android package to start
361
android_activity: The name of the android activity
362
device_serial: The device serial number
363
"""
364
if not android_package:
365
raise AttributeError("android_package must be passed in")
366
self.mobile_options = {"androidPackage": android_package}
367
if android_activity:
368
self.mobile_options["androidActivity"] = android_activity
369
if device_serial:
370
self.mobile_options["androidDeviceSerial"] = device_serial
371
372
@abstractmethod
373
def to_capabilities(self):
374
"""Convert options into capabilities dictionary."""
375
376
@property
377
@abstractmethod
378
def default_capabilities(self):
379
"""Return minimal capabilities necessary as a dictionary."""
380
381
def ignore_local_proxy_environment_variables(self) -> None:
382
"""Ignore HTTP_PROXY and HTTPS_PROXY environment variables."""
383
self._ignore_local_proxy = True
384
385
386
class ArgOptions(BaseOptions):
387
BINARY_LOCATION_ERROR = "Binary Location Must be a String"
388
# FedCM capability key
389
FEDCM_CAPABILITY = "fedcm:accounts"
390
391
def __init__(self) -> None:
392
super().__init__()
393
self._arguments: list[str] = []
394
395
@property
396
def arguments(self):
397
"""Returns a list of arguments needed for the browser."""
398
return self._arguments
399
400
def add_argument(self, argument: str) -> None:
401
"""Adds an argument to the list.
402
403
Args:
404
argument: Sets the arguments
405
"""
406
if argument:
407
self._arguments.append(argument)
408
else:
409
raise ValueError("argument can not be null")
410
411
def ignore_local_proxy_environment_variables(self) -> None:
412
"""Ignore HTTP_PROXY and HTTPS_PROXY environment variables.
413
414
This method is deprecated; use a Proxy instance with ProxyType.DIRECT instead.
415
"""
416
warnings.warn(
417
"using ignore_local_proxy_environment_variables in Options has been deprecated, "
418
"instead, create a Proxy instance with ProxyType.DIRECT to ignore proxy settings, "
419
"pass the proxy instance into a ClientConfig constructor, "
420
"pass the client config instance into the Webdriver constructor",
421
DeprecationWarning,
422
stacklevel=2,
423
)
424
425
super().ignore_local_proxy_environment_variables()
426
427
def to_capabilities(self):
428
return self._caps
429
430
@property
431
def default_capabilities(self):
432
return {}
433
434