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.
- misc/understanding_idevice_protocol_layers.md +10 -5
- pymobiledevice3/__main__.py +171 -46
- pymobiledevice3/_version.py +2 -2
- pymobiledevice3/bonjour.py +22 -21
- pymobiledevice3/cli/activation.py +24 -22
- pymobiledevice3/cli/afc.py +49 -41
- pymobiledevice3/cli/amfi.py +13 -18
- pymobiledevice3/cli/apps.py +71 -65
- pymobiledevice3/cli/backup.py +134 -93
- pymobiledevice3/cli/bonjour.py +31 -29
- pymobiledevice3/cli/cli_common.py +175 -232
- pymobiledevice3/cli/companion_proxy.py +12 -12
- pymobiledevice3/cli/crash.py +95 -52
- pymobiledevice3/cli/developer/__init__.py +62 -0
- pymobiledevice3/cli/developer/accessibility/__init__.py +65 -0
- pymobiledevice3/cli/developer/accessibility/settings.py +43 -0
- pymobiledevice3/cli/developer/arbitration.py +50 -0
- pymobiledevice3/cli/developer/condition.py +33 -0
- pymobiledevice3/cli/developer/core_device.py +294 -0
- pymobiledevice3/cli/developer/debugserver.py +244 -0
- pymobiledevice3/cli/developer/dvt/__init__.py +438 -0
- pymobiledevice3/cli/developer/dvt/core_profile_session.py +295 -0
- pymobiledevice3/cli/developer/dvt/simulate_location.py +56 -0
- pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +69 -0
- pymobiledevice3/cli/developer/dvt/sysmon/process.py +188 -0
- pymobiledevice3/cli/developer/fetch_symbols.py +108 -0
- pymobiledevice3/cli/developer/simulate_location.py +51 -0
- pymobiledevice3/cli/diagnostics/__init__.py +75 -0
- pymobiledevice3/cli/diagnostics/battery.py +47 -0
- pymobiledevice3/cli/idam.py +42 -0
- pymobiledevice3/cli/lockdown.py +70 -75
- pymobiledevice3/cli/mounter.py +99 -57
- pymobiledevice3/cli/notification.py +38 -26
- pymobiledevice3/cli/pcap.py +36 -20
- pymobiledevice3/cli/power_assertion.py +15 -16
- pymobiledevice3/cli/processes.py +11 -17
- pymobiledevice3/cli/profile.py +120 -75
- pymobiledevice3/cli/provision.py +27 -26
- pymobiledevice3/cli/remote.py +109 -100
- pymobiledevice3/cli/restore.py +134 -129
- pymobiledevice3/cli/springboard.py +50 -50
- pymobiledevice3/cli/syslog.py +145 -65
- pymobiledevice3/cli/usbmux.py +66 -27
- pymobiledevice3/cli/version.py +2 -5
- pymobiledevice3/cli/webinspector.py +232 -156
- pymobiledevice3/exceptions.py +6 -2
- pymobiledevice3/lockdown.py +5 -1
- pymobiledevice3/lockdown_service_provider.py +5 -0
- pymobiledevice3/remote/remote_service_discovery.py +18 -10
- pymobiledevice3/restore/device.py +28 -4
- pymobiledevice3/restore/restore.py +2 -2
- pymobiledevice3/service_connection.py +15 -12
- pymobiledevice3/services/afc.py +731 -220
- pymobiledevice3/services/device_link.py +45 -31
- pymobiledevice3/services/idam.py +20 -0
- pymobiledevice3/services/lockdown_service.py +12 -9
- pymobiledevice3/services/mobile_config.py +1 -0
- pymobiledevice3/services/mobilebackup2.py +6 -3
- pymobiledevice3/services/os_trace.py +97 -55
- pymobiledevice3/services/remote_fetch_symbols.py +13 -8
- pymobiledevice3/services/screenshot.py +2 -2
- pymobiledevice3/services/web_protocol/alert.py +8 -8
- pymobiledevice3/services/web_protocol/automation_session.py +87 -79
- pymobiledevice3/services/web_protocol/cdp_screencast.py +2 -1
- pymobiledevice3/services/web_protocol/driver.py +71 -70
- pymobiledevice3/services/web_protocol/element.py +58 -56
- pymobiledevice3/services/web_protocol/selenium_api.py +47 -47
- pymobiledevice3/services/web_protocol/session_protocol.py +3 -2
- pymobiledevice3/services/web_protocol/switch_to.py +23 -19
- pymobiledevice3/services/webinspector.py +42 -67
- {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/METADATA +5 -3
- {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/RECORD +76 -61
- pymobiledevice3/cli/completions.py +0 -50
- pymobiledevice3/cli/developer.py +0 -1539
- pymobiledevice3/cli/diagnostics.py +0 -110
- {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/WHEEL +0 -0
- {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/entry_points.txt +0 -0
- {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/licenses/LICENSE +0 -0
- {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
|
-
|
|
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(
|
|
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(
|
|
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)[
|
|
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
|
|
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()
|