Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/py/selenium/webdriver/common/options.py
1864 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
from typing import Optional
22
23
from selenium.common.exceptions import InvalidArgumentException
24
from selenium.webdriver.common.proxy import Proxy
25
26
27
class PageLoadStrategy(str, Enum):
28
"""Enum of possible page load strategies.
29
30
Selenium support following strategies:
31
* normal (default) - waits for all resources to download
32
* eager - DOM access is ready, but other resources like images may still be loading
33
* none - does not block `WebDriver` at all
34
35
Docs: https://www.selenium.dev/documentation/webdriver/drivers/options/#pageloadstrategy.
36
"""
37
38
normal = "normal"
39
eager = "eager"
40
none = "none"
41
42
43
class _BaseOptionsDescriptor:
44
def __init__(self, name):
45
self.name = name
46
47
def __get__(self, obj, cls):
48
if self.name == "enableBidi":
49
# whether BiDi is or will be enabled
50
value = obj._caps.get("webSocketUrl")
51
return value is True or isinstance(value, str)
52
if self.name == "webSocketUrl":
53
# Return socket url or None if not created yet
54
value = obj._caps.get(self.name)
55
return None if not isinstance(value, str) else value
56
if self.name in ("acceptInsecureCerts", "strictFileInteractability", "setWindowRect", "se:downloadsEnabled"):
57
return obj._caps.get(self.name, False)
58
return obj._caps.get(self.name)
59
60
def __set__(self, obj, value):
61
if self.name == "enableBidi":
62
obj.set_capability("webSocketUrl", value)
63
else:
64
obj.set_capability(self.name, value)
65
66
67
class _PageLoadStrategyDescriptor:
68
"""Determines the point at which a navigation command is returned:
69
https://w3c.github.io/webdriver/#dfn-table-of-page-load-strategies.
70
71
:param strategy: the strategy corresponding to a document readiness state
72
"""
73
74
def __init__(self, name):
75
self.name = name
76
77
def __get__(self, obj, cls):
78
return obj._caps.get(self.name)
79
80
def __set__(self, obj, value):
81
if value in ("normal", "eager", "none"):
82
obj.set_capability(self.name, value)
83
else:
84
raise ValueError("Strategy can only be one of the following: normal, eager, none")
85
86
87
class _UnHandledPromptBehaviorDescriptor:
88
"""How the driver should respond when an alert is present and the:
89
command sent is not handling the alert:
90
https://w3c.github.io/webdriver/#dfn-table-of-page-load-strategies:
91
92
:param behavior: behavior to use when an alert is encountered
93
94
:returns: Values for implicit timeout, pageLoad timeout and script timeout if set (in milliseconds)
95
"""
96
97
def __init__(self, name):
98
self.name = name
99
100
def __get__(self, obj, cls):
101
return obj._caps.get(self.name)
102
103
def __set__(self, obj, value):
104
if value in ("dismiss", "accept", "dismiss and notify", "accept and notify", "ignore"):
105
obj.set_capability(self.name, value)
106
else:
107
raise ValueError(
108
"Behavior can only be one of the following: dismiss, accept, dismiss and notify, "
109
"accept and notify, ignore"
110
)
111
112
113
class _TimeoutsDescriptor:
114
"""How long the driver should wait for actions to complete before:
115
returning an error https://w3c.github.io/webdriver/#timeouts:
116
117
:param timeouts: values in milliseconds for implicit wait, page load and script timeout
118
119
:returns: Values for implicit timeout, pageLoad timeout and script timeout if set (in milliseconds)
120
"""
121
122
def __init__(self, name):
123
self.name = name
124
125
def __get__(self, obj, cls):
126
return obj._caps.get(self.name)
127
128
def __set__(self, obj, value):
129
if all(x in ("implicit", "pageLoad", "script") for x in value.keys()):
130
obj.set_capability(self.name, value)
131
else:
132
raise ValueError("Timeout keys can only be one of the following: implicit, pageLoad, script")
133
134
135
class _ProxyDescriptor:
136
""":Returns: Proxy if set, otherwise None."""
137
138
def __init__(self, name):
139
self.name = name
140
141
def __get__(self, obj, cls):
142
return obj._proxy
143
144
def __set__(self, obj, value):
145
if not isinstance(value, Proxy):
146
raise InvalidArgumentException("Only Proxy objects can be passed in.")
147
obj._proxy = value
148
obj._caps[self.name] = value.to_capabilities()
149
150
151
class BaseOptions(metaclass=ABCMeta):
152
"""Base class for individual browser options."""
153
154
browser_version = _BaseOptionsDescriptor("browserVersion")
155
"""Gets and Sets the version of the browser.
156
157
Usage:
158
------
159
- Get
160
- `self.browser_version`
161
- Set
162
- `self.browser_version` = `value`
163
164
Parameters:
165
-----------
166
`value`: `str`
167
168
Returns:
169
--------
170
- Get
171
- `str`
172
- Set
173
- `None`
174
"""
175
176
platform_name = _BaseOptionsDescriptor("platformName")
177
"""Gets and Sets name of the platform.
178
179
Usage:
180
------
181
- Get
182
- `self.platform_name`
183
- Set
184
- `self.platform_name` = `value`
185
186
Parameters:
187
-----------
188
`value`: `str`
189
190
Returns:
191
--------
192
- Get
193
- `str`
194
- Set
195
- `None`
196
"""
197
198
accept_insecure_certs = _BaseOptionsDescriptor("acceptInsecureCerts")
199
"""Gets and Set whether the session accepts insecure certificates.
200
201
Usage:
202
------
203
- Get
204
- `self.accept_insecure_certs`
205
- Set
206
- `self.accept_insecure_certs` = `value`
207
208
Parameters:
209
-----------
210
`value`: `bool`
211
212
Returns:
213
--------
214
- Get
215
- `bool`
216
- Set
217
- `None`
218
"""
219
220
strict_file_interactability = _BaseOptionsDescriptor("strictFileInteractability")
221
"""Gets and Sets whether session is about file interactability.
222
223
Usage:
224
------
225
- Get
226
- `self.strict_file_interactability`
227
- Set
228
- `self.strict_file_interactability` = `value`
229
230
Parameters:
231
-----------
232
`value`: `bool`
233
234
Returns:
235
--------
236
- Get
237
- `bool`
238
- Set
239
- `None`
240
"""
241
242
set_window_rect = _BaseOptionsDescriptor("setWindowRect")
243
"""Gets and Sets window size and position.
244
245
Usage:
246
------
247
- Get
248
- `self.set_window_rect`
249
- Set
250
- `self.set_window_rect` = `value`
251
252
Parameters:
253
-----------
254
`value`: `bool`
255
256
Returns:
257
--------
258
- Get
259
- `bool`
260
- Set
261
- `None`
262
"""
263
264
enable_bidi = _BaseOptionsDescriptor("enableBidi")
265
"""Gets and Set whether the session has WebDriverBiDi enabled.
266
267
Usage:
268
------
269
- Get
270
- `self.enable_bidi`
271
- Set
272
- `self.enable_bidi` = `value`
273
274
Parameters:
275
-----------
276
`value`: `bool`
277
278
Returns:
279
--------
280
- Get
281
- `bool`
282
- Set
283
- `None`
284
"""
285
286
page_load_strategy = _PageLoadStrategyDescriptor("pageLoadStrategy")
287
""":Gets and Sets page load strategy, the default is "normal".
288
289
Usage:
290
------
291
- Get
292
- `self.page_load_strategy`
293
- Set
294
- `self.page_load_strategy` = `value`
295
296
Parameters:
297
-----------
298
`value`: `str`
299
300
Returns:
301
--------
302
- Get
303
- `str`
304
- Set
305
- `None`
306
"""
307
308
unhandled_prompt_behavior = _UnHandledPromptBehaviorDescriptor("unhandledPromptBehavior")
309
""":Gets and Sets unhandled prompt behavior, the default is "dismiss and
310
notify".
311
312
Usage:
313
------
314
- Get
315
- `self.unhandled_prompt_behavior`
316
- Set
317
- `self.unhandled_prompt_behavior` = `value`
318
319
Parameters:
320
-----------
321
`value`: `str`
322
323
Returns:
324
--------
325
- Get
326
- `str`
327
- Set
328
- `None`
329
"""
330
331
timeouts = _TimeoutsDescriptor("timeouts")
332
""":Gets and Sets implicit timeout, pageLoad timeout and script timeout if
333
set (in milliseconds)
334
335
Usage:
336
------
337
- Get
338
- `self.timeouts`
339
- Set
340
- `self.timeouts` = `value`
341
342
Parameters:
343
-----------
344
`value`: `dict`
345
346
Returns:
347
--------
348
- Get
349
- `dict`
350
- Set
351
- `None`
352
"""
353
354
proxy = _ProxyDescriptor("proxy")
355
"""Sets and Gets Proxy.
356
357
Usage:
358
------
359
- Get
360
- `self.proxy`
361
- Set
362
- `self.proxy` = `value`
363
364
Parameters:
365
-----------
366
`value`: `Proxy`
367
368
Returns:
369
--------
370
- Get
371
- `Proxy`
372
- Set
373
- `None`
374
"""
375
376
enable_downloads = _BaseOptionsDescriptor("se:downloadsEnabled")
377
"""Gets and Sets whether session can download files.
378
379
Usage:
380
------
381
- Get
382
- `self.enable_downloads`
383
- Set
384
- `self.enable_downloads` = `value`
385
386
Parameters:
387
-----------
388
`value`: `bool`
389
390
Returns:
391
--------
392
- Get
393
- `bool`
394
- Set
395
- `None`
396
"""
397
398
web_socket_url = _BaseOptionsDescriptor("webSocketUrl")
399
"""Gets and Sets WebSocket URL.
400
401
Usage:
402
------
403
- Get
404
- `self.web_socket_url`
405
- Set
406
- `self.web_socket_url` = `value`
407
408
Parameters:
409
-----------
410
`value`: `str`
411
412
Returns:
413
--------
414
- Get
415
- `bool`
416
- Set
417
- `None`
418
"""
419
420
def __init__(self) -> None:
421
super().__init__()
422
self._caps = self.default_capabilities
423
self._proxy = None
424
self.set_capability("pageLoadStrategy", PageLoadStrategy.normal)
425
self.mobile_options: Optional[dict[str, str]] = None
426
self._ignore_local_proxy = False
427
428
@property
429
def capabilities(self):
430
return self._caps
431
432
def set_capability(self, name, value) -> None:
433
"""Sets a capability."""
434
self._caps[name] = value
435
436
def enable_mobile(
437
self,
438
android_package: Optional[str] = None,
439
android_activity: Optional[str] = None,
440
device_serial: Optional[str] = None,
441
) -> None:
442
"""Enables mobile browser use for browsers that support it.
443
444
:Args:
445
android_activity: The name of the android package to start
446
"""
447
if not android_package:
448
raise AttributeError("android_package must be passed in")
449
self.mobile_options = {"androidPackage": android_package}
450
if android_activity:
451
self.mobile_options["androidActivity"] = android_activity
452
if device_serial:
453
self.mobile_options["androidDeviceSerial"] = device_serial
454
455
@abstractmethod
456
def to_capabilities(self):
457
"""Convert options into capabilities dictionary."""
458
459
@property
460
@abstractmethod
461
def default_capabilities(self):
462
"""Return minimal capabilities necessary as a dictionary."""
463
464
def ignore_local_proxy_environment_variables(self) -> None:
465
"""By calling this you will ignore HTTP_PROXY and HTTPS_PROXY from
466
being picked up and used."""
467
self._ignore_local_proxy = True
468
469
470
class ArgOptions(BaseOptions):
471
BINARY_LOCATION_ERROR = "Binary Location Must be a String"
472
# FedCM capability key
473
FEDCM_CAPABILITY = "fedcm:accounts"
474
475
def __init__(self) -> None:
476
super().__init__()
477
self._arguments: list[str] = []
478
479
@property
480
def arguments(self):
481
""":Returns: A list of arguments needed for the browser."""
482
return self._arguments
483
484
def add_argument(self, argument: str) -> None:
485
"""Adds an argument to the list.
486
487
:Args:
488
- Sets the arguments
489
"""
490
if argument:
491
self._arguments.append(argument)
492
else:
493
raise ValueError("argument can not be null")
494
495
def ignore_local_proxy_environment_variables(self) -> None:
496
"""By calling this you will ignore HTTP_PROXY and HTTPS_PROXY from
497
being picked up and used."""
498
warnings.warn(
499
"using ignore_local_proxy_environment_variables in Options has been deprecated, "
500
"instead, create a Proxy instance with ProxyType.DIRECT to ignore proxy settings, "
501
"pass the proxy instance into a ClientConfig constructor, "
502
"pass the client config instance into the Webdriver constructor",
503
DeprecationWarning,
504
stacklevel=2,
505
)
506
507
super().ignore_local_proxy_environment_variables()
508
509
def to_capabilities(self):
510
return self._caps
511
512
@property
513
def default_capabilities(self):
514
return {}
515
516