pymobiledevice3 5.0.4__py3-none-any.whl → 7.0.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.
Files changed (79) hide show
  1. misc/understanding_idevice_protocol_layers.md +10 -5
  2. pymobiledevice3/__main__.py +171 -46
  3. pymobiledevice3/_version.py +2 -2
  4. pymobiledevice3/bonjour.py +22 -21
  5. pymobiledevice3/cli/activation.py +24 -22
  6. pymobiledevice3/cli/afc.py +49 -41
  7. pymobiledevice3/cli/amfi.py +13 -18
  8. pymobiledevice3/cli/apps.py +71 -65
  9. pymobiledevice3/cli/backup.py +134 -93
  10. pymobiledevice3/cli/bonjour.py +31 -29
  11. pymobiledevice3/cli/cli_common.py +175 -232
  12. pymobiledevice3/cli/companion_proxy.py +12 -12
  13. pymobiledevice3/cli/crash.py +95 -52
  14. pymobiledevice3/cli/developer/__init__.py +62 -0
  15. pymobiledevice3/cli/developer/accessibility/__init__.py +65 -0
  16. pymobiledevice3/cli/developer/accessibility/settings.py +43 -0
  17. pymobiledevice3/cli/developer/arbitration.py +50 -0
  18. pymobiledevice3/cli/developer/condition.py +33 -0
  19. pymobiledevice3/cli/developer/core_device.py +294 -0
  20. pymobiledevice3/cli/developer/debugserver.py +244 -0
  21. pymobiledevice3/cli/developer/dvt/__init__.py +438 -0
  22. pymobiledevice3/cli/developer/dvt/core_profile_session.py +295 -0
  23. pymobiledevice3/cli/developer/dvt/simulate_location.py +56 -0
  24. pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +69 -0
  25. pymobiledevice3/cli/developer/dvt/sysmon/process.py +188 -0
  26. pymobiledevice3/cli/developer/fetch_symbols.py +108 -0
  27. pymobiledevice3/cli/developer/simulate_location.py +51 -0
  28. pymobiledevice3/cli/diagnostics/__init__.py +75 -0
  29. pymobiledevice3/cli/diagnostics/battery.py +47 -0
  30. pymobiledevice3/cli/idam.py +42 -0
  31. pymobiledevice3/cli/lockdown.py +70 -75
  32. pymobiledevice3/cli/mounter.py +99 -57
  33. pymobiledevice3/cli/notification.py +38 -26
  34. pymobiledevice3/cli/pcap.py +36 -20
  35. pymobiledevice3/cli/power_assertion.py +15 -16
  36. pymobiledevice3/cli/processes.py +11 -17
  37. pymobiledevice3/cli/profile.py +120 -75
  38. pymobiledevice3/cli/provision.py +27 -26
  39. pymobiledevice3/cli/remote.py +109 -100
  40. pymobiledevice3/cli/restore.py +134 -129
  41. pymobiledevice3/cli/springboard.py +50 -50
  42. pymobiledevice3/cli/syslog.py +145 -65
  43. pymobiledevice3/cli/usbmux.py +66 -27
  44. pymobiledevice3/cli/version.py +2 -5
  45. pymobiledevice3/cli/webinspector.py +232 -156
  46. pymobiledevice3/exceptions.py +6 -2
  47. pymobiledevice3/lockdown.py +5 -1
  48. pymobiledevice3/lockdown_service_provider.py +5 -0
  49. pymobiledevice3/remote/remote_service_discovery.py +18 -10
  50. pymobiledevice3/restore/device.py +28 -4
  51. pymobiledevice3/restore/restore.py +2 -2
  52. pymobiledevice3/service_connection.py +15 -12
  53. pymobiledevice3/services/afc.py +731 -220
  54. pymobiledevice3/services/device_link.py +45 -31
  55. pymobiledevice3/services/idam.py +20 -0
  56. pymobiledevice3/services/lockdown_service.py +12 -9
  57. pymobiledevice3/services/mobile_config.py +1 -0
  58. pymobiledevice3/services/mobilebackup2.py +6 -3
  59. pymobiledevice3/services/os_trace.py +97 -55
  60. pymobiledevice3/services/remote_fetch_symbols.py +13 -8
  61. pymobiledevice3/services/screenshot.py +2 -2
  62. pymobiledevice3/services/web_protocol/alert.py +8 -8
  63. pymobiledevice3/services/web_protocol/automation_session.py +87 -79
  64. pymobiledevice3/services/web_protocol/cdp_screencast.py +2 -1
  65. pymobiledevice3/services/web_protocol/driver.py +71 -70
  66. pymobiledevice3/services/web_protocol/element.py +58 -56
  67. pymobiledevice3/services/web_protocol/selenium_api.py +47 -47
  68. pymobiledevice3/services/web_protocol/session_protocol.py +3 -2
  69. pymobiledevice3/services/web_protocol/switch_to.py +23 -19
  70. pymobiledevice3/services/webinspector.py +42 -67
  71. {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/METADATA +5 -3
  72. {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/RECORD +76 -61
  73. pymobiledevice3/cli/completions.py +0 -50
  74. pymobiledevice3/cli/developer.py +0 -1539
  75. pymobiledevice3/cli/diagnostics.py +0 -110
  76. {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/WHEEL +0 -0
  77. {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/entry_points.txt +0 -0
  78. {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/licenses/LICENSE +0 -0
  79. {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,11 @@
1
+ import importlib.resources
1
2
  import json
2
3
  from dataclasses import dataclass
3
4
  from enum import Enum
4
- from pathlib import Path
5
5
 
6
- RESOURCES = Path(__file__).parent.parent.parent / "resources" / "webinspector"
6
+ import pymobiledevice3.resources
7
+
8
+ RESOURCES = importlib.resources.files(pymobiledevice3.resources) / "webinspector"
7
9
  FIND_NODES = (RESOURCES / "find_nodes.js").read_text()
8
10
 
9
11
 
@@ -167,62 +169,62 @@ class AutomationSession:
167
169
  def id_(self):
168
170
  return self.protocol.id_
169
171
 
170
- def start_session(self):
171
- handle = self.protocol.createBrowsingContext()["handle"]
172
- self.switch_to_top_level_browsing_context(handle)
172
+ async def start_session(self):
173
+ handle = (await self.protocol.createBrowsingContext())["handle"]
174
+ await self.switch_to_top_level_browsing_context(handle)
173
175
 
174
- def stop_session(self):
176
+ async def stop_session(self):
175
177
  self.top_level_handle = ""
176
178
  self.current_handle = ""
177
179
  self.current_parent_handle = ""
178
- for handle in self.get_window_handles():
179
- self.protocol.closeBrowsingContext(handle=handle)
180
+ for handle in await self.get_window_handles():
181
+ await self.protocol.closeBrowsingContext(handle=handle)
180
182
 
181
- def create_window(self, type_):
183
+ async def create_window(self, type_):
182
184
  type_ = type_.capitalize()
183
185
  params = {"presentationHint": type_} if type_ else {}
184
- return self.protocol.createBrowsingContext(**params)["handle"]
186
+ return (await self.protocol.createBrowsingContext(**params))["handle"]
185
187
 
186
- def close_window(self):
188
+ async def close_window(self):
187
189
  if not self.top_level_handle:
188
190
  return
189
191
  handle = self.top_level_handle
190
- self.protocol.closeBrowsingContext(handle=handle)
192
+ await self.protocol.closeBrowsingContext(handle=handle)
191
193
 
192
- def maximize_window(self):
193
- self.protocol.maximizeWindowOfBrowsingContext(handle=self.top_level_handle)
194
+ async def maximize_window(self):
195
+ await self.protocol.maximizeWindowOfBrowsingContext(handle=self.top_level_handle)
194
196
 
195
- def hide_window(self):
196
- self.protocol.hideWindowOfBrowsingContext(handle=self.top_level_handle)
197
+ async def hide_window(self):
198
+ await self.protocol.hideWindowOfBrowsingContext(handle=self.top_level_handle)
197
199
 
198
- def get_browsing_context(self):
199
- return self.protocol.getBrowsingContext(handle=self.top_level_handle)["context"]
200
+ async def get_browsing_context(self):
201
+ return (await self.protocol.getBrowsingContext(handle=self.top_level_handle))["context"]
200
202
 
201
- def get_window_handles(self):
202
- contexts = self.protocol.getBrowsingContexts()
203
+ async def get_window_handles(self):
204
+ contexts = await self.protocol.getBrowsingContexts()
203
205
  return [c["handle"] for c in contexts["contexts"]]
204
206
 
205
- def set_window_frame(self, x=None, y=None, width=None, height=None):
207
+ async def set_window_frame(self, x=None, y=None, width=None, height=None):
206
208
  params = {}
207
209
  if x is not None and y is not None:
208
210
  params["origin"] = {"x": x, "y": y}
209
211
  if width is not None and height is not None:
210
212
  params["size"] = {"width": width, "height": height}
211
- self.protocol.setWindowFrameOfBrowsingContext(handle=self.top_level_handle, **params)
213
+ await self.protocol.setWindowFrameOfBrowsingContext(handle=self.top_level_handle, **params)
212
214
 
213
- def add_single_cookie(self, cookie):
214
- self.protocol.addSingleCookie(browsingContextHandle=self.top_level_handle, cookie=cookie)
215
+ async def add_single_cookie(self, cookie):
216
+ await self.protocol.addSingleCookie(browsingContextHandle=self.top_level_handle, cookie=cookie)
215
217
 
216
- def delete_all_cookies(self):
217
- self.protocol.deleteAllCookies(browsingContextHandle=self.top_level_handle)
218
+ async def delete_all_cookies(self):
219
+ await self.protocol.deleteAllCookies(browsingContextHandle=self.top_level_handle)
218
220
 
219
- def delete_single_cookie(self, name):
220
- self.protocol.deleteSingleCookie(browsingContextHandle=self.top_level_handle, cookieName=name)
221
+ async def delete_single_cookie(self, name):
222
+ await self.protocol.deleteSingleCookie(browsingContextHandle=self.top_level_handle, cookieName=name)
221
223
 
222
- def get_all_cookies(self):
223
- return self.protocol.getAllCookies(browsingContextHandle=self.top_level_handle)["cookies"]
224
+ async def get_all_cookies(self):
225
+ return (await self.protocol.getAllCookies(browsingContextHandle=self.top_level_handle))["cookies"]
224
226
 
225
- def execute_script(self, script, args, async_=False):
227
+ async def execute_script(self, script, args, async_=False):
226
228
  parameters = {
227
229
  "browsingContextHandle": self.top_level_handle,
228
230
  "function": "function(){\n" + script + "\n}",
@@ -234,13 +236,13 @@ class AutomationSession:
234
236
  parameters["expectsImplicitCallbackArgument"] = True
235
237
  if self.script_timeout != -1:
236
238
  parameters["callbackTimeout"] = self.script_timeout
237
- result = self.protocol.evaluateJavaScriptFunction(**parameters, wait_for_response=not async_)
239
+ result = await self.protocol.evaluateJavaScriptFunction(**parameters, wait_for_response=not async_)
238
240
  if async_:
239
241
  return result
240
242
  else:
241
243
  return json.loads(result["result"])
242
244
 
243
- def evaluate_js_function(self, function, *args, implicit_callback=False, include_frame=True):
245
+ async def evaluate_js_function(self, function, *args, implicit_callback=False, include_frame=True):
244
246
  params = {
245
247
  "browsingContextHandle": self.top_level_handle,
246
248
  "function": function,
@@ -250,11 +252,11 @@ class AutomationSession:
250
252
  params["frameHandle"] = self.current_handle
251
253
  if implicit_callback:
252
254
  params["expectsImplicitCallbackArgument"] = True
253
- result = self.protocol.evaluateJavaScriptFunction(**params)
255
+ result = await self.protocol.evaluateJavaScriptFunction(**params)
254
256
  return json.loads(result["result"])
255
257
 
256
- def find_elements(self, by, value, single: bool = True, root=None):
257
- self.wait_for_navigation_to_complete()
258
+ async def find_elements(self, by, value, single: bool = True, root=None):
259
+ await self.wait_for_navigation_to_complete()
258
260
  by = by.value if isinstance(by, By) else by
259
261
  if by == By.ID.value:
260
262
  by = By.CSS_SELECTOR.value
@@ -278,10 +280,10 @@ class AutomationSession:
278
280
  parameters["frameHandle"] = self.current_handle
279
281
  if self.implicit_wait_timeout:
280
282
  parameters["callbackTimeout"] = self.implicit_wait_timeout + 1000
281
- result = json.loads(self.protocol.evaluateJavaScriptFunction(**parameters)["result"])
283
+ result = json.loads((await self.protocol.evaluateJavaScriptFunction(**parameters))["result"])
282
284
  return result
283
285
 
284
- def screenshot_as_base64(self, scroll=False, node_id="", clip=True):
286
+ async def screenshot_as_base64(self, scroll=False, node_id="", clip=True):
285
287
  params = {"handle": self.top_level_handle, "clipToViewport": clip}
286
288
  if self.current_handle:
287
289
  params["frameHandle"] = self.current_handle
@@ -289,42 +291,46 @@ class AutomationSession:
289
291
  params["scrollIntoViewIfNeeded"] = True
290
292
  if node_id:
291
293
  params["nodeHandle"] = node_id
292
- return self.protocol.takeScreenshot(**params)["data"]
294
+ return (await self.protocol.takeScreenshot(**params))["data"]
293
295
 
294
- def switch_to_top_level_browsing_context(self, top_level_handle):
296
+ async def switch_to_top_level_browsing_context(self, top_level_handle):
295
297
  self.top_level_handle = top_level_handle
296
298
  self.current_handle = ""
297
299
  self.current_parent_handle = ""
298
300
 
299
- def switch_to_browsing_context(self, handle):
301
+ async def switch_to_browsing_context(self, handle):
300
302
  self.current_handle = handle
301
303
  if not self.current_handle:
302
304
  self.current_parent_handle = ""
303
305
  return
304
306
 
305
- resp = self.protocol.resolveParentFrameHandle(
307
+ resp = await self.protocol.resolveParentFrameHandle(
306
308
  browsingContextHandle=self.top_level_handle, frameHandle=self.current_handle
307
309
  )
308
310
  self.current_parent_handle = resp["result"]
309
311
 
310
- def switch_to_browsing_context_frame(self, context, frame):
311
- self.protocol.switchToBrowsingContext(browsingContextHandle=context, frameHandle=frame)
312
+ async def switch_to_browsing_context_frame(self, context, frame):
313
+ await self.protocol.switchToBrowsingContext(browsingContextHandle=context, frameHandle=frame)
312
314
 
313
- def navigate_broswing_context(self, url):
314
- self.protocol.navigateBrowsingContext(
315
+ async def navigate_broswing_context(self, url):
316
+ await self.protocol.navigateBrowsingContext(
315
317
  handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout, url=url
316
318
  )
317
319
 
318
- def go_back_in_browsing_context(self):
319
- self.protocol.goBackInBrowsingContext(handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout)
320
+ async def go_back_in_browsing_context(self):
321
+ await self.protocol.goBackInBrowsingContext(
322
+ handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout
323
+ )
320
324
 
321
- def go_forward_in_browsing_context(self):
322
- self.protocol.goForwardInBrowsingContext(handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout)
325
+ async def go_forward_in_browsing_context(self):
326
+ await self.protocol.goForwardInBrowsingContext(
327
+ handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout
328
+ )
323
329
 
324
- def reload_browsing_context(self):
325
- self.protocol.reloadBrowsingContext(handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout)
330
+ async def reload_browsing_context(self):
331
+ await self.protocol.reloadBrowsingContext(handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout)
326
332
 
327
- def switch_to_frame(self, frame_ordinal=None, frame_handle=None):
333
+ async def switch_to_frame(self, frame_ordinal=None, frame_handle=None):
328
334
  params = {"browsingContextHandle": self.top_level_handle}
329
335
  if self.current_handle:
330
336
  params["frameHandle"] = self.current_handle
@@ -332,23 +338,23 @@ class AutomationSession:
332
338
  params["ordinal"] = frame_ordinal
333
339
  elif frame_handle is not None:
334
340
  params["nodeHandle"] = frame_handle.node_id
335
- resp = self.protocol.resolveChildFrameHandle(**params)["result"]
336
- self.switch_to_browsing_context_frame(self.top_level_handle, resp)
337
- self.switch_to_browsing_context(resp)
341
+ resp = (await self.protocol.resolveChildFrameHandle(**params))["result"]
342
+ await self.switch_to_browsing_context_frame(self.top_level_handle, resp)
343
+ await self.switch_to_browsing_context(resp)
338
344
 
339
- def switch_to_window(self, handle):
340
- self.switch_to_browsing_context_frame(handle, "")
341
- self.switch_to_top_level_browsing_context(handle)
345
+ async def switch_to_window(self, handle):
346
+ await self.switch_to_browsing_context_frame(handle, "")
347
+ await self.switch_to_top_level_browsing_context(handle)
342
348
 
343
- def perform_keyboard_interactions(self, interactions):
349
+ async def perform_keyboard_interactions(self, interactions):
344
350
  for interaction in interactions:
345
351
  type_ = interaction["type"]
346
352
  interaction["type"] = type_.value if isinstance(type_, KeyboardInteractionType) else type_
347
- self.protocol.performKeyboardInteractions(handle=self.top_level_handle, interactions=interactions)
353
+ await self.protocol.performKeyboardInteractions(handle=self.top_level_handle, interactions=interactions)
348
354
 
349
- def perform_mouse_interaction(self, x, y, button: MouseButton, interaction: MouseInteraction, modifiers=None):
355
+ async def perform_mouse_interaction(self, x, y, button: MouseButton, interaction: MouseInteraction, modifiers=None):
350
356
  modifiers = [] if modifiers is None else modifiers
351
- self.protocol.performMouseInteraction(
357
+ await self.protocol.performMouseInteraction(
352
358
  handle=self.top_level_handle,
353
359
  position={"x": x, "y": y},
354
360
  button=button.value,
@@ -356,7 +362,7 @@ class AutomationSession:
356
362
  modifiers=modifiers,
357
363
  )
358
364
 
359
- def perform_interaction_sequence(self, sources, steps):
365
+ async def perform_interaction_sequence(self, sources, steps):
360
366
  params = {
361
367
  "handle": self.top_level_handle,
362
368
  "inputSources": sources,
@@ -364,30 +370,32 @@ class AutomationSession:
364
370
  }
365
371
  if self.current_handle:
366
372
  params["frameHandle"] = self.current_handle
367
- self.protocol.performInteractionSequence(**params)
373
+ await self.protocol.performInteractionSequence(**params)
368
374
 
369
- def wait_for_navigation_to_complete(self):
375
+ async def wait_for_navigation_to_complete(self):
370
376
  params = {"browsingContextHandle": self.top_level_handle, "pageLoadTimeout": self.page_load_timeout}
371
377
  if self.current_handle:
372
378
  params["frameHandle"] = self.current_handle
373
- self.protocol.waitForNavigationToComplete(**params)
379
+ await self.protocol.waitForNavigationToComplete(**params)
374
380
 
375
- def accept_current_javascript_dialog(self):
376
- self.protocol.acceptCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)
381
+ async def accept_current_javascript_dialog(self):
382
+ await self.protocol.acceptCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)
377
383
 
378
- def dismiss_current_javascript_dialog(self):
379
- self.protocol.dismissCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)
384
+ async def dismiss_current_javascript_dialog(self):
385
+ await self.protocol.dismissCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)
380
386
 
381
- def set_user_input_for_current_javascript_prompt(self, user_input):
382
- self.protocol.setUserInputForCurrentJavaScriptPrompt(
387
+ async def set_user_input_for_current_javascript_prompt(self, user_input):
388
+ await self.protocol.setUserInputForCurrentJavaScriptPrompt(
383
389
  browsingContextHandle=self.top_level_handle, userInput=user_input
384
390
  )
385
391
 
386
- def message_of_current_javascript_dialog(self):
387
- return self.protocol.messageOfCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)["message"]
392
+ async def message_of_current_javascript_dialog(self):
393
+ return (await self.protocol.messageOfCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle))[
394
+ "message"
395
+ ]
388
396
 
389
- def compute_element_layout(self, node_id, scroll_if_needed, coordinate_system):
390
- return self.protocol.computeElementLayout(
397
+ async def compute_element_layout(self, node_id, scroll_if_needed, coordinate_system):
398
+ return await self.protocol.computeElementLayout(
391
399
  browsingContextHandle=self.top_level_handle,
392
400
  nodeHandle=node_id,
393
401
  scrollIntoViewIfNeeded=scroll_if_needed,
@@ -395,8 +403,8 @@ class AutomationSession:
395
403
  frameHandle="" if self.current_handle is None else self.current_handle,
396
404
  )
397
405
 
398
- def select_option_element(self, node_id):
399
- self.protocol.selectOptionElement(
406
+ async def select_option_element(self, node_id):
407
+ await self.protocol.selectOptionElement(
400
408
  browsingContextHandle=self.top_level_handle,
401
409
  nodeHandle=node_id,
402
410
  frameHandle="" if self.current_handle is None else self.current_handle,
@@ -3,6 +3,7 @@ import contextlib
3
3
  from base64 import b64decode, b64encode
4
4
  from datetime import datetime
5
5
  from io import BytesIO
6
+ from typing import Optional
6
7
 
7
8
  from PIL import Image
8
9
 
@@ -28,7 +29,7 @@ class ScreenCast:
28
29
  self.device_height = 0
29
30
  self.page_scale_factor = 0
30
31
  self._run = True
31
- self.recording_task = None # type: asyncio.Task | None
32
+ self.recording_task: Optional[asyncio.Task] = None
32
33
 
33
34
  @property
34
35
  def scale(self) -> float:
@@ -1,4 +1,5 @@
1
1
  from dataclasses import asdict, dataclass
2
+ from typing import Optional
2
3
 
3
4
  from pymobiledevice3.services.web_protocol.automation_session import RESOURCES, Point, Rect, Size
4
5
  from pymobiledevice3.services.web_protocol.element import WebElement
@@ -34,106 +35,106 @@ class WebDriver(SeleniumApi):
34
35
  self.session = session
35
36
  self.switch_to = SwitchTo(session)
36
37
 
37
- def add_cookie(self, cookie: Cookie):
38
+ async def add_cookie(self, cookie: Cookie):
38
39
  """Adds a cookie to your current session."""
39
40
  if isinstance(cookie, Cookie):
40
41
  cookie = asdict(cookie)
41
- self.session.add_single_cookie(cookie)
42
+ await self.session.add_single_cookie(cookie)
42
43
 
43
- def back(self):
44
+ async def back(self):
44
45
  """Goes one step backward in the browser history."""
45
- self.session.wait_for_navigation_to_complete()
46
- self.session.go_back_in_browsing_context()
47
- self.session.switch_to_browsing_context("")
46
+ await self.session.wait_for_navigation_to_complete()
47
+ await self.session.go_back_in_browsing_context()
48
+ await self.session.switch_to_browsing_context("")
48
49
 
49
- def close(self):
50
+ async def close(self):
50
51
  """Closes the current window."""
51
- self.session.close_window()
52
+ await self.session.close_window()
52
53
 
53
54
  @property
54
- def current_url(self):
55
+ async def current_url(self):
55
56
  """Gets the URL of the current page."""
56
- self.session.wait_for_navigation_to_complete()
57
- return self.session.get_browsing_context()["url"]
57
+ await self.session.wait_for_navigation_to_complete()
58
+ return (await self.session.get_browsing_context())["url"]
58
59
 
59
60
  @property
60
- def current_window_handle(self):
61
+ async def current_window_handle(self):
61
62
  """Returns the handle of the current window."""
62
- return self.session.get_browsing_context()["handle"]
63
+ return (await self.session.get_browsing_context())["handle"]
63
64
 
64
- def delete_all_cookies(self):
65
+ async def delete_all_cookies(self):
65
66
  """Delete all cookies in the scope of the session."""
66
- self.session.delete_all_cookies()
67
+ await self.session.delete_all_cookies()
67
68
 
68
- def delete_cookie(self, name: str):
69
+ async def delete_cookie(self, name: str):
69
70
  """Deletes a single cookie with the given name."""
70
- self.session.delete_single_cookie(name)
71
+ await self.session.delete_single_cookie(name)
71
72
 
72
- def execute_async_script(self, script: str, *args):
73
+ async def execute_async_script(self, script: str, *args):
73
74
  """
74
75
  Asynchronously Executes JavaScript in the current window/frame.
75
76
  :param script: The JavaScript to execute.
76
77
  :param args: Any applicable arguments for your JavaScript.
77
78
  """
78
- return self.session.execute_script(script, args, async_=True)
79
+ return await self.session.execute_script(script, args, async_=True)
79
80
 
80
- def execute_script(self, script: str, *args):
81
+ async def execute_script(self, script: str, *args):
81
82
  """
82
83
  Synchronously Executes JavaScript in the current window/frame.
83
84
  :param script: The JavaScript to execute.
84
85
  :param args: Any applicable arguments for your JavaScript.
85
86
  """
86
- return self.session.execute_script(script, args)
87
+ return await self.session.execute_script(script, args)
87
88
 
88
- def find_element(self, by=By.ID, value=None) -> WebElement:
89
+ async def find_element(self, by=By.ID, value=None) -> Optional[WebElement]:
89
90
  """Find an element given a By strategy and locator."""
90
- elem = self.session.find_elements(by, value)
91
+ elem = await self.session.find_elements(by, value)
91
92
  return None if elem is None else WebElement(self.session, elem)
92
93
 
93
- def find_elements(self, by=By.ID, value=None) -> list[WebElement]:
94
+ async def find_elements(self, by=By.ID, value=None) -> list[WebElement]:
94
95
  """Find elements given a By strategy and locator."""
95
- elements = self.session.find_elements(by, value, single=False)
96
+ elements = await self.session.find_elements(by, value, single=False)
96
97
  return [WebElement(self.session, elem) for elem in elements]
97
98
 
98
- def forward(self):
99
+ async def forward(self):
99
100
  """Goes one step forward in the browser history."""
100
- self.session.wait_for_navigation_to_complete()
101
- self.session.go_forward_in_browsing_context()
102
- self.session.switch_to_browsing_context("")
101
+ await self.session.wait_for_navigation_to_complete()
102
+ await self.session.go_forward_in_browsing_context()
103
+ await self.session.switch_to_browsing_context("")
103
104
 
104
- def fullscreen_window(self):
105
+ async def fullscreen_window(self):
105
106
  """Invokes the window manager-specific 'full screen' operation."""
106
- self.session.evaluate_js_function(ENTER_FULLSCREEN, implicit_callback=True)
107
+ await self.session.evaluate_js_function(ENTER_FULLSCREEN, implicit_callback=True)
107
108
 
108
- def get(self, url: str):
109
+ async def get(self, url: str):
109
110
  """Loads a web page in the current browser session."""
110
- self.session.wait_for_navigation_to_complete()
111
- self.session.navigate_broswing_context(url)
112
- self.session.switch_to_browsing_context("")
111
+ await self.session.wait_for_navigation_to_complete()
112
+ await self.session.navigate_broswing_context(url)
113
+ await self.session.switch_to_browsing_context("")
113
114
 
114
- def get_cookie(self, name: str) -> Cookie:
115
+ async def get_cookie(self, name: str) -> Cookie:
115
116
  """Get a single cookie by name. Returns the cookie if found, None if not."""
116
- for cookie in self.get_cookies():
117
+ for cookie in await self.get_cookies():
117
118
  if cookie.name == name:
118
119
  return cookie
119
120
 
120
- def get_cookies(self) -> list[Cookie]:
121
+ async def get_cookies(self) -> list[Cookie]:
121
122
  """Returns cookies visible in the current session."""
122
- return list(map(Cookie.from_automation, self.session.get_all_cookies()))
123
+ return list(map(Cookie.from_automation, await self.session.get_all_cookies()))
123
124
 
124
125
  @property
125
- def screenshot_as_base64(self) -> str:
126
+ async def screenshot_as_base64(self) -> str:
126
127
  """Gets the screenshot of the current window as a base64 encoded string."""
127
- return self.session.screenshot_as_base64()
128
+ return await self.session.screenshot_as_base64()
128
129
 
129
- def get_window_position(self) -> Point:
130
+ async def get_window_position(self) -> Point:
130
131
  """Gets the x,y position of the current window."""
131
- rect = self.get_window_rect()
132
+ rect = await self.get_window_rect()
132
133
  return Point(x=rect.x, y=rect.y)
133
134
 
134
- def get_window_rect(self) -> Rect:
135
+ async def get_window_rect(self) -> Rect:
135
136
  """Gets the x, y coordinates of the window as well as height and width of the current window."""
136
- context = self.session.get_browsing_context()
137
+ context = await self.session.get_browsing_context()
137
138
  return Rect(
138
139
  context["windowOrigin"]["x"],
139
140
  context["windowOrigin"]["y"],
@@ -141,57 +142,57 @@ class WebDriver(SeleniumApi):
141
142
  context["windowSize"]["height"],
142
143
  )
143
144
 
144
- def get_window_size(self) -> Size:
145
+ async def get_window_size(self) -> Size:
145
146
  """Gets the width and height of the current window."""
146
- rect = self.get_window_rect()
147
+ rect = await self.get_window_rect()
147
148
  return Size(height=rect.height, width=rect.width)
148
149
 
149
150
  def implicitly_wait(self, time_to_wait):
150
151
  """Sets a sticky timeout to implicitly wait for an element to be found, or a command to complete."""
151
152
  self.session.implicit_wait_timeout = time_to_wait * 1000
152
153
 
153
- def maximize_window(self):
154
+ async def maximize_window(self):
154
155
  """Maximizes the current window."""
155
- self.session.maximize_window()
156
+ await self.session.maximize_window()
156
157
 
157
- def minimize_window(self):
158
+ async def minimize_window(self):
158
159
  """Invokes the window manager-specific 'minimize' operation."""
159
- self.session.hide_window()
160
+ await self.session.hide_window()
160
161
 
161
162
  @property
162
- def page_source(self) -> str:
163
+ async def page_source(self) -> str:
163
164
  """Gets the source of the current page."""
164
- return self.session.evaluate_js_function("function() { return document.documentElement.outerHTML; }")
165
+ return await self.session.evaluate_js_function("function() { return document.documentElement.outerHTML; }")
165
166
 
166
- def refresh(self):
167
+ async def refresh(self):
167
168
  """Refreshes the current page."""
168
- self.session.wait_for_navigation_to_complete()
169
- self.session.reload_browsing_context()
170
- self.session.switch_to_browsing_context("")
169
+ await self.session.wait_for_navigation_to_complete()
170
+ await self.session.reload_browsing_context()
171
+ await self.session.switch_to_browsing_context("")
171
172
 
172
- def set_window_position(self, x, y):
173
+ async def set_window_position(self, x, y):
173
174
  """Sets the x,y position of the current window."""
174
- self.set_window_rect(x=int(x, 0), y=int(y, 0))
175
+ await self.set_window_rect(x=int(x, 0), y=int(y, 0))
175
176
 
176
- def set_window_rect(self, x=None, y=None, width=None, height=None):
177
+ async def set_window_rect(self, x=None, y=None, width=None, height=None):
177
178
  """Sets the x, y coordinates of the window as well as height and width of the current window."""
178
- self.session.set_window_frame(x, y, width, height)
179
+ await self.session.set_window_frame(x, y, width, height)
179
180
 
180
- def set_window_size(self, width, height):
181
+ async def set_window_size(self, width, height):
181
182
  """Sets the width and height of the current window."""
182
- self.set_window_rect(width=int(width, 0), height=int(height, 0))
183
+ await self.set_window_rect(width=int(width, 0), height=int(height, 0))
183
184
 
184
- def start_session(self):
185
+ async def start_session(self):
185
186
  """Creates a new session."""
186
- self.session.start_session()
187
+ await self.session.start_session()
187
188
 
188
189
  @property
189
- def title(self) -> str:
190
+ async def title(self) -> str:
190
191
  """Returns the title of the current page."""
191
- self.session.wait_for_navigation_to_complete()
192
- return self.session.evaluate_js_function("function() { return document.title; }")
192
+ await self.session.wait_for_navigation_to_complete()
193
+ return await self.session.evaluate_js_function("function() { return document.title; }")
193
194
 
194
195
  @property
195
- def window_handles(self) -> list[str]:
196
+ async def window_handles(self) -> list[str]:
196
197
  """Returns the handles of all windows within the current session."""
197
- return self.session.get_window_handles()
198
+ return await self.session.get_window_handles()