pymobiledevice3 5.3.2__py3-none-any.whl → 6.0.1__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.
- pymobiledevice3/_version.py +2 -2
- pymobiledevice3/cli/webinspector.py +90 -60
- pymobiledevice3/services/web_protocol/alert.py +8 -8
- pymobiledevice3/services/web_protocol/automation_session.py +83 -77
- pymobiledevice3/services/web_protocol/driver.py +71 -70
- pymobiledevice3/services/web_protocol/element.py +57 -55
- 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.3.2.dist-info → pymobiledevice3-6.0.1.dist-info}/METADATA +1 -1
- {pymobiledevice3-5.3.2.dist-info → pymobiledevice3-6.0.1.dist-info}/RECORD +16 -16
- {pymobiledevice3-5.3.2.dist-info → pymobiledevice3-6.0.1.dist-info}/WHEEL +0 -0
- {pymobiledevice3-5.3.2.dist-info → pymobiledevice3-6.0.1.dist-info}/entry_points.txt +0 -0
- {pymobiledevice3-5.3.2.dist-info → pymobiledevice3-6.0.1.dist-info}/licenses/LICENSE +0 -0
- {pymobiledevice3-5.3.2.dist-info → pymobiledevice3-6.0.1.dist-info}/top_level.txt +0 -0
pymobiledevice3/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '
|
|
32
|
-
__version_tuple__ = version_tuple = (
|
|
31
|
+
__version__ = version = '6.0.1'
|
|
32
|
+
__version_tuple__ = version_tuple = (6, 0, 1)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -2,14 +2,16 @@ import asyncio
|
|
|
2
2
|
import logging
|
|
3
3
|
import re
|
|
4
4
|
from abc import ABC, abstractmethod
|
|
5
|
-
from
|
|
5
|
+
from asyncio import CancelledError
|
|
6
|
+
from collections.abc import AsyncIterator, Iterable
|
|
6
7
|
from contextlib import asynccontextmanager
|
|
7
8
|
from functools import update_wrapper
|
|
8
|
-
from typing import Optional
|
|
9
|
+
from typing import Optional, Union
|
|
9
10
|
|
|
10
11
|
import click
|
|
11
12
|
import inquirer3
|
|
12
13
|
import IPython
|
|
14
|
+
import nest_asyncio
|
|
13
15
|
import uvicorn
|
|
14
16
|
from inquirer3.themes import GreenPassion
|
|
15
17
|
from prompt_toolkit import HTML, PromptSession
|
|
@@ -161,13 +163,22 @@ def reload_pages(inspector: WebinspectorService):
|
|
|
161
163
|
inspector.flush_input(2)
|
|
162
164
|
|
|
163
165
|
|
|
164
|
-
def create_webinspector_and_launch_app(lockdown: LockdownClient, timeout: float, app: str):
|
|
166
|
+
async def create_webinspector_and_launch_app(lockdown: LockdownClient, timeout: float, app: str):
|
|
165
167
|
inspector = WebinspectorService(lockdown=lockdown)
|
|
166
|
-
inspector.connect(timeout)
|
|
167
|
-
application = inspector.open_app(app)
|
|
168
|
+
await inspector.connect(timeout)
|
|
169
|
+
application = await inspector.open_app(app)
|
|
168
170
|
return inspector, application
|
|
169
171
|
|
|
170
172
|
|
|
173
|
+
async def opened_tabs_task(service_provider: LockdownClient, timeout):
|
|
174
|
+
inspector = WebinspectorService(lockdown=service_provider)
|
|
175
|
+
await inspector.connect(timeout)
|
|
176
|
+
application_pages = await inspector.get_open_application_pages(timeout=timeout)
|
|
177
|
+
for application_page in application_pages:
|
|
178
|
+
print(application_page)
|
|
179
|
+
await inspector.close()
|
|
180
|
+
|
|
181
|
+
|
|
171
182
|
@webinspector.command(cls=Command)
|
|
172
183
|
@click.option("-t", "--timeout", default=3, show_default=True, type=float)
|
|
173
184
|
@catch_errors
|
|
@@ -181,12 +192,21 @@ def opened_tabs(service_provider: LockdownClient, timeout):
|
|
|
181
192
|
|
|
182
193
|
iOS < 18: Settings -> Safari -> Advanced -> Web Inspector
|
|
183
194
|
"""
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
inspector
|
|
195
|
+
asyncio.run(opened_tabs_task(service_provider, timeout), debug=True)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
@catch_errors
|
|
199
|
+
async def launch_task(service_provider: LockdownClient, url, timeout):
|
|
200
|
+
inspector, safari = await create_webinspector_and_launch_app(service_provider, timeout, SAFARI)
|
|
201
|
+
session = await inspector.automation_session(safari)
|
|
202
|
+
driver = WebDriver(session)
|
|
203
|
+
print("Starting session")
|
|
204
|
+
await driver.start_session()
|
|
205
|
+
print("Getting URL")
|
|
206
|
+
await driver.get(url)
|
|
207
|
+
OSUTILS.wait_return()
|
|
208
|
+
await session.stop_session()
|
|
209
|
+
await inspector.close()
|
|
190
210
|
|
|
191
211
|
|
|
192
212
|
@webinspector.command(cls=Command)
|
|
@@ -207,16 +227,7 @@ def launch(service_provider: LockdownClient, url, timeout):
|
|
|
207
227
|
Settings -> Safari -> Advanced -> Remote Automation
|
|
208
228
|
|
|
209
229
|
"""
|
|
210
|
-
|
|
211
|
-
session = inspector.automation_session(safari)
|
|
212
|
-
driver = WebDriver(session)
|
|
213
|
-
print("Starting session")
|
|
214
|
-
driver.start_session()
|
|
215
|
-
print("Getting URL")
|
|
216
|
-
driver.get(url)
|
|
217
|
-
OSUTILS.wait_return()
|
|
218
|
-
session.stop_session()
|
|
219
|
-
inspector.close()
|
|
230
|
+
asyncio.run(launch_task(service_provider, url, timeout), debug=True)
|
|
220
231
|
|
|
221
232
|
|
|
222
233
|
SHELL_USAGE = """
|
|
@@ -240,9 +251,28 @@ driver.add_cookie(
|
|
|
240
251
|
"""
|
|
241
252
|
|
|
242
253
|
|
|
254
|
+
@catch_errors
|
|
255
|
+
async def shell_task(service_provider: LockdownClient, timeout):
|
|
256
|
+
inspector, safari = await create_webinspector_and_launch_app(service_provider, timeout, SAFARI)
|
|
257
|
+
session = await inspector.automation_session(safari)
|
|
258
|
+
driver = WebDriver(session)
|
|
259
|
+
try:
|
|
260
|
+
nest_asyncio.apply()
|
|
261
|
+
IPython.embed(
|
|
262
|
+
header=highlight(SHELL_USAGE, lexers.PythonLexer(), formatters.Terminal256Formatter(style="native")),
|
|
263
|
+
user_ns={
|
|
264
|
+
"driver": driver,
|
|
265
|
+
"Cookie": Cookie,
|
|
266
|
+
"By": By,
|
|
267
|
+
},
|
|
268
|
+
)
|
|
269
|
+
finally:
|
|
270
|
+
await session.stop_session()
|
|
271
|
+
await inspector.close()
|
|
272
|
+
|
|
273
|
+
|
|
243
274
|
@webinspector.command(cls=Command)
|
|
244
275
|
@click.option("-t", "--timeout", default=3, show_default=True, type=float)
|
|
245
|
-
@catch_errors
|
|
246
276
|
def shell(service_provider: LockdownClient, timeout):
|
|
247
277
|
"""
|
|
248
278
|
Create an IPython shell for interacting with a WebView.
|
|
@@ -256,21 +286,7 @@ def shell(service_provider: LockdownClient, timeout):
|
|
|
256
286
|
Settings -> Safari -> Advanced -> Web Inspector
|
|
257
287
|
Settings -> Safari -> Advanced -> Remote Automation
|
|
258
288
|
"""
|
|
259
|
-
|
|
260
|
-
session = inspector.automation_session(safari)
|
|
261
|
-
driver = WebDriver(session)
|
|
262
|
-
try:
|
|
263
|
-
IPython.embed(
|
|
264
|
-
header=highlight(SHELL_USAGE, lexers.PythonLexer(), formatters.Terminal256Formatter(style="native")),
|
|
265
|
-
user_ns={
|
|
266
|
-
"driver": driver,
|
|
267
|
-
"Cookie": Cookie,
|
|
268
|
-
"By": By,
|
|
269
|
-
},
|
|
270
|
-
)
|
|
271
|
-
finally:
|
|
272
|
-
session.stop_session()
|
|
273
|
-
inspector.close()
|
|
289
|
+
asyncio.run(shell_task(service_provider, timeout), debug=True)
|
|
274
290
|
|
|
275
291
|
|
|
276
292
|
@webinspector.command(cls=Command)
|
|
@@ -333,42 +349,56 @@ def cdp(service_provider: LockdownClient, host, port):
|
|
|
333
349
|
)
|
|
334
350
|
|
|
335
351
|
|
|
336
|
-
def get_js_completions(jsshell: "JsShell", obj: str, prefix: str) ->
|
|
352
|
+
async def get_js_completions(jsshell: "JsShell", obj: str, prefix: str) -> AsyncIterator[Completion]:
|
|
337
353
|
if obj in JS_RESERVED_WORDS:
|
|
338
|
-
return
|
|
354
|
+
return
|
|
339
355
|
|
|
340
|
-
completions = []
|
|
341
356
|
try:
|
|
342
|
-
for key in
|
|
343
|
-
jsshell.evaluate_expression(SCRIPT.format(object=obj), return_by_value=True)
|
|
344
|
-
):
|
|
357
|
+
for key in await jsshell.evaluate_expression(SCRIPT.format(object=obj), return_by_value=True):
|
|
345
358
|
if not key.startswith(prefix):
|
|
346
359
|
continue
|
|
347
|
-
|
|
348
|
-
except Exception:
|
|
360
|
+
yield Completion(key.removeprefix(prefix), display=key)
|
|
361
|
+
except (Exception, CancelledError):
|
|
349
362
|
# ignore every possible exception
|
|
350
363
|
pass
|
|
351
|
-
return completions
|
|
352
364
|
|
|
353
365
|
|
|
354
366
|
class JsShellCompleter(Completer):
|
|
355
367
|
def __init__(self, jsshell: "JsShell"):
|
|
356
368
|
self.jsshell = jsshell
|
|
357
369
|
|
|
358
|
-
def
|
|
370
|
+
def get_completions_async(
|
|
371
|
+
self,
|
|
372
|
+
document: Document,
|
|
373
|
+
complete_event: CompleteEvent,
|
|
374
|
+
) -> Union[AsyncIterator[Completion], Iterable[Completion]]:
|
|
375
|
+
# Build the JS expression we want to inspect
|
|
359
376
|
text = f"globalThis.{document.text_before_cursor}"
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
377
|
+
|
|
378
|
+
# Extract identifiers / dotted paths
|
|
379
|
+
matches = re.findall(r"[a-zA-Z_][a-zA-Z_0-9.]+", text)
|
|
380
|
+
if not matches:
|
|
381
|
+
# async *generator*: just end, don't return a list
|
|
382
|
+
return iter(())
|
|
383
|
+
|
|
384
|
+
text = matches[-1]
|
|
364
385
|
if "." in text:
|
|
365
386
|
js_obj, prefix = text.rsplit(".", 1)
|
|
366
387
|
else:
|
|
367
388
|
js_obj = text
|
|
368
389
|
prefix = ""
|
|
369
390
|
|
|
391
|
+
# This should return an iterable of Completion (or something we can wrap)
|
|
370
392
|
return get_js_completions(self.jsshell, js_obj, prefix)
|
|
371
393
|
|
|
394
|
+
# Optional: keep sync completions empty so PTK knows we prefer async
|
|
395
|
+
def get_completions(
|
|
396
|
+
self,
|
|
397
|
+
document: Document,
|
|
398
|
+
complete_event: CompleteEvent,
|
|
399
|
+
) -> Iterable[Completion]:
|
|
400
|
+
return []
|
|
401
|
+
|
|
372
402
|
|
|
373
403
|
class JsShell(ABC):
|
|
374
404
|
def __init__(self) -> None:
|
|
@@ -436,7 +466,7 @@ class AutomationJsShell(JsShell):
|
|
|
436
466
|
inspector, application = create_webinspector_and_launch_app(lockdown, timeout, SAFARI)
|
|
437
467
|
automation_session = inspector.automation_session(application)
|
|
438
468
|
driver = WebDriver(automation_session)
|
|
439
|
-
driver.start_session()
|
|
469
|
+
await driver.start_session()
|
|
440
470
|
try:
|
|
441
471
|
yield cls(driver)
|
|
442
472
|
finally:
|
|
@@ -444,10 +474,10 @@ class AutomationJsShell(JsShell):
|
|
|
444
474
|
inspector.close()
|
|
445
475
|
|
|
446
476
|
async def evaluate_expression(self, exp: str, return_by_value: bool = False):
|
|
447
|
-
return self.driver.execute_script(f"return {exp}")
|
|
477
|
+
return await self.driver.execute_script(f"return {exp}")
|
|
448
478
|
|
|
449
479
|
async def navigate(self, url: str):
|
|
450
|
-
self.driver.get(url)
|
|
480
|
+
await self.driver.get(url)
|
|
451
481
|
|
|
452
482
|
|
|
453
483
|
class InspectorJsShell(JsShell):
|
|
@@ -459,10 +489,10 @@ class InspectorJsShell(JsShell):
|
|
|
459
489
|
@asynccontextmanager
|
|
460
490
|
async def create(cls, lockdown: LockdownClient, timeout: float, open_safari: bool) -> "InspectorJsShell":
|
|
461
491
|
inspector = WebinspectorService(lockdown=lockdown)
|
|
462
|
-
inspector.connect(timeout)
|
|
492
|
+
await inspector.connect(timeout)
|
|
463
493
|
if open_safari:
|
|
464
|
-
_ = inspector.open_app(SAFARI)
|
|
465
|
-
application_page = cls.query_page(inspector, bundle_identifier=SAFARI if open_safari else None)
|
|
494
|
+
_ = await inspector.open_app(SAFARI)
|
|
495
|
+
application_page = await cls.query_page(inspector, bundle_identifier=SAFARI if open_safari else None)
|
|
466
496
|
if application_page is None:
|
|
467
497
|
raise click.exceptions.Exit()
|
|
468
498
|
|
|
@@ -473,7 +503,7 @@ class InspectorJsShell(JsShell):
|
|
|
473
503
|
try:
|
|
474
504
|
yield cls(inspector_session)
|
|
475
505
|
finally:
|
|
476
|
-
inspector.close()
|
|
506
|
+
await inspector.close()
|
|
477
507
|
|
|
478
508
|
async def evaluate_expression(self, exp: str, return_by_value: bool = False):
|
|
479
509
|
return await self.inspector_session.runtime_evaluate(exp, return_by_value=return_by_value)
|
|
@@ -482,10 +512,10 @@ class InspectorJsShell(JsShell):
|
|
|
482
512
|
await self.inspector_session.navigate_to_url(url)
|
|
483
513
|
|
|
484
514
|
@staticmethod
|
|
485
|
-
def query_page(
|
|
515
|
+
async def query_page(
|
|
486
516
|
inspector: WebinspectorService, bundle_identifier: Optional[str] = None
|
|
487
517
|
) -> Optional[ApplicationPage]:
|
|
488
|
-
available_pages = inspector.get_open_application_pages(timeout=1)
|
|
518
|
+
available_pages = await inspector.get_open_application_pages(timeout=1)
|
|
489
519
|
if bundle_identifier is not None:
|
|
490
520
|
available_pages = [
|
|
491
521
|
application_page
|
|
@@ -5,22 +5,22 @@ class Alert:
|
|
|
5
5
|
"""
|
|
6
6
|
self.session = session
|
|
7
7
|
|
|
8
|
-
def accept(self):
|
|
8
|
+
async def accept(self):
|
|
9
9
|
"""Accepts the alert available."""
|
|
10
|
-
self.session.accept_current_javascript_dialog()
|
|
10
|
+
await self.session.accept_current_javascript_dialog()
|
|
11
11
|
|
|
12
|
-
def dismiss(self):
|
|
12
|
+
async def dismiss(self):
|
|
13
13
|
"""Dismisses the alert available."""
|
|
14
|
-
self.session.dismiss_current_javascript_dialog()
|
|
14
|
+
await self.session.dismiss_current_javascript_dialog()
|
|
15
15
|
|
|
16
|
-
def send_keys(self, text: str):
|
|
16
|
+
async def send_keys(self, text: str):
|
|
17
17
|
"""
|
|
18
18
|
Send Keys to the Alert.
|
|
19
19
|
:param text: Text to send to prompts.
|
|
20
20
|
"""
|
|
21
|
-
self.session.set_user_input_for_current_javascript_prompt(text)
|
|
21
|
+
await self.session.set_user_input_for_current_javascript_prompt(text)
|
|
22
22
|
|
|
23
23
|
@property
|
|
24
|
-
def text(self) -> str:
|
|
24
|
+
async def text(self) -> str:
|
|
25
25
|
"""Gets the text of the Alert."""
|
|
26
|
-
return self.session.message_of_current_javascript_dialog()
|
|
26
|
+
return await self.session.message_of_current_javascript_dialog()
|
|
@@ -167,62 +167,62 @@ class AutomationSession:
|
|
|
167
167
|
def id_(self):
|
|
168
168
|
return self.protocol.id_
|
|
169
169
|
|
|
170
|
-
def start_session(self):
|
|
171
|
-
handle = self.protocol.createBrowsingContext()["handle"]
|
|
172
|
-
self.switch_to_top_level_browsing_context(handle)
|
|
170
|
+
async def start_session(self):
|
|
171
|
+
handle = (await self.protocol.createBrowsingContext())["handle"]
|
|
172
|
+
await self.switch_to_top_level_browsing_context(handle)
|
|
173
173
|
|
|
174
|
-
def stop_session(self):
|
|
174
|
+
async def stop_session(self):
|
|
175
175
|
self.top_level_handle = ""
|
|
176
176
|
self.current_handle = ""
|
|
177
177
|
self.current_parent_handle = ""
|
|
178
|
-
for handle in self.get_window_handles():
|
|
179
|
-
self.protocol.closeBrowsingContext(handle=handle)
|
|
178
|
+
for handle in await self.get_window_handles():
|
|
179
|
+
await self.protocol.closeBrowsingContext(handle=handle)
|
|
180
180
|
|
|
181
|
-
def create_window(self, type_):
|
|
181
|
+
async def create_window(self, type_):
|
|
182
182
|
type_ = type_.capitalize()
|
|
183
183
|
params = {"presentationHint": type_} if type_ else {}
|
|
184
|
-
return self.protocol.createBrowsingContext(**params)["handle"]
|
|
184
|
+
return (await self.protocol.createBrowsingContext(**params))["handle"]
|
|
185
185
|
|
|
186
|
-
def close_window(self):
|
|
186
|
+
async def close_window(self):
|
|
187
187
|
if not self.top_level_handle:
|
|
188
188
|
return
|
|
189
189
|
handle = self.top_level_handle
|
|
190
|
-
self.protocol.closeBrowsingContext(handle=handle)
|
|
190
|
+
await self.protocol.closeBrowsingContext(handle=handle)
|
|
191
191
|
|
|
192
|
-
def maximize_window(self):
|
|
193
|
-
self.protocol.maximizeWindowOfBrowsingContext(handle=self.top_level_handle)
|
|
192
|
+
async def maximize_window(self):
|
|
193
|
+
await self.protocol.maximizeWindowOfBrowsingContext(handle=self.top_level_handle)
|
|
194
194
|
|
|
195
|
-
def hide_window(self):
|
|
196
|
-
self.protocol.hideWindowOfBrowsingContext(handle=self.top_level_handle)
|
|
195
|
+
async def hide_window(self):
|
|
196
|
+
await self.protocol.hideWindowOfBrowsingContext(handle=self.top_level_handle)
|
|
197
197
|
|
|
198
|
-
def get_browsing_context(self):
|
|
199
|
-
return self.protocol.getBrowsingContext(handle=self.top_level_handle)["context"]
|
|
198
|
+
async def get_browsing_context(self):
|
|
199
|
+
return (await self.protocol.getBrowsingContext(handle=self.top_level_handle))["context"]
|
|
200
200
|
|
|
201
|
-
def get_window_handles(self):
|
|
202
|
-
contexts = self.protocol.getBrowsingContexts()
|
|
201
|
+
async def get_window_handles(self):
|
|
202
|
+
contexts = await self.protocol.getBrowsingContexts()
|
|
203
203
|
return [c["handle"] for c in contexts["contexts"]]
|
|
204
204
|
|
|
205
|
-
def set_window_frame(self, x=None, y=None, width=None, height=None):
|
|
205
|
+
async def set_window_frame(self, x=None, y=None, width=None, height=None):
|
|
206
206
|
params = {}
|
|
207
207
|
if x is not None and y is not None:
|
|
208
208
|
params["origin"] = {"x": x, "y": y}
|
|
209
209
|
if width is not None and height is not None:
|
|
210
210
|
params["size"] = {"width": width, "height": height}
|
|
211
|
-
self.protocol.setWindowFrameOfBrowsingContext(handle=self.top_level_handle, **params)
|
|
211
|
+
await self.protocol.setWindowFrameOfBrowsingContext(handle=self.top_level_handle, **params)
|
|
212
212
|
|
|
213
|
-
def add_single_cookie(self, cookie):
|
|
214
|
-
self.protocol.addSingleCookie(browsingContextHandle=self.top_level_handle, cookie=cookie)
|
|
213
|
+
async def add_single_cookie(self, cookie):
|
|
214
|
+
await self.protocol.addSingleCookie(browsingContextHandle=self.top_level_handle, cookie=cookie)
|
|
215
215
|
|
|
216
|
-
def delete_all_cookies(self):
|
|
217
|
-
self.protocol.deleteAllCookies(browsingContextHandle=self.top_level_handle)
|
|
216
|
+
async def delete_all_cookies(self):
|
|
217
|
+
await self.protocol.deleteAllCookies(browsingContextHandle=self.top_level_handle)
|
|
218
218
|
|
|
219
|
-
def delete_single_cookie(self, name):
|
|
220
|
-
self.protocol.deleteSingleCookie(browsingContextHandle=self.top_level_handle, cookieName=name)
|
|
219
|
+
async def delete_single_cookie(self, name):
|
|
220
|
+
await self.protocol.deleteSingleCookie(browsingContextHandle=self.top_level_handle, cookieName=name)
|
|
221
221
|
|
|
222
|
-
def get_all_cookies(self):
|
|
223
|
-
return self.protocol.getAllCookies(browsingContextHandle=self.top_level_handle)["cookies"]
|
|
222
|
+
async def get_all_cookies(self):
|
|
223
|
+
return (await self.protocol.getAllCookies(browsingContextHandle=self.top_level_handle))["cookies"]
|
|
224
224
|
|
|
225
|
-
def execute_script(self, script, args, async_=False):
|
|
225
|
+
async def execute_script(self, script, args, async_=False):
|
|
226
226
|
parameters = {
|
|
227
227
|
"browsingContextHandle": self.top_level_handle,
|
|
228
228
|
"function": "function(){\n" + script + "\n}",
|
|
@@ -234,13 +234,13 @@ class AutomationSession:
|
|
|
234
234
|
parameters["expectsImplicitCallbackArgument"] = True
|
|
235
235
|
if self.script_timeout != -1:
|
|
236
236
|
parameters["callbackTimeout"] = self.script_timeout
|
|
237
|
-
result = self.protocol.evaluateJavaScriptFunction(**parameters, wait_for_response=not async_)
|
|
237
|
+
result = await self.protocol.evaluateJavaScriptFunction(**parameters, wait_for_response=not async_)
|
|
238
238
|
if async_:
|
|
239
239
|
return result
|
|
240
240
|
else:
|
|
241
241
|
return json.loads(result["result"])
|
|
242
242
|
|
|
243
|
-
def evaluate_js_function(self, function, *args, implicit_callback=False, include_frame=True):
|
|
243
|
+
async def evaluate_js_function(self, function, *args, implicit_callback=False, include_frame=True):
|
|
244
244
|
params = {
|
|
245
245
|
"browsingContextHandle": self.top_level_handle,
|
|
246
246
|
"function": function,
|
|
@@ -250,11 +250,11 @@ class AutomationSession:
|
|
|
250
250
|
params["frameHandle"] = self.current_handle
|
|
251
251
|
if implicit_callback:
|
|
252
252
|
params["expectsImplicitCallbackArgument"] = True
|
|
253
|
-
result = self.protocol.evaluateJavaScriptFunction(**params)
|
|
253
|
+
result = await self.protocol.evaluateJavaScriptFunction(**params)
|
|
254
254
|
return json.loads(result["result"])
|
|
255
255
|
|
|
256
|
-
def find_elements(self, by, value, single: bool = True, root=None):
|
|
257
|
-
self.wait_for_navigation_to_complete()
|
|
256
|
+
async def find_elements(self, by, value, single: bool = True, root=None):
|
|
257
|
+
await self.wait_for_navigation_to_complete()
|
|
258
258
|
by = by.value if isinstance(by, By) else by
|
|
259
259
|
if by == By.ID.value:
|
|
260
260
|
by = By.CSS_SELECTOR.value
|
|
@@ -278,10 +278,10 @@ class AutomationSession:
|
|
|
278
278
|
parameters["frameHandle"] = self.current_handle
|
|
279
279
|
if self.implicit_wait_timeout:
|
|
280
280
|
parameters["callbackTimeout"] = self.implicit_wait_timeout + 1000
|
|
281
|
-
result = json.loads(self.protocol.evaluateJavaScriptFunction(**parameters)["result"])
|
|
281
|
+
result = json.loads((await self.protocol.evaluateJavaScriptFunction(**parameters))["result"])
|
|
282
282
|
return result
|
|
283
283
|
|
|
284
|
-
def screenshot_as_base64(self, scroll=False, node_id="", clip=True):
|
|
284
|
+
async def screenshot_as_base64(self, scroll=False, node_id="", clip=True):
|
|
285
285
|
params = {"handle": self.top_level_handle, "clipToViewport": clip}
|
|
286
286
|
if self.current_handle:
|
|
287
287
|
params["frameHandle"] = self.current_handle
|
|
@@ -289,42 +289,46 @@ class AutomationSession:
|
|
|
289
289
|
params["scrollIntoViewIfNeeded"] = True
|
|
290
290
|
if node_id:
|
|
291
291
|
params["nodeHandle"] = node_id
|
|
292
|
-
return self.protocol.takeScreenshot(**params)["data"]
|
|
292
|
+
return (await self.protocol.takeScreenshot(**params))["data"]
|
|
293
293
|
|
|
294
|
-
def switch_to_top_level_browsing_context(self, top_level_handle):
|
|
294
|
+
async def switch_to_top_level_browsing_context(self, top_level_handle):
|
|
295
295
|
self.top_level_handle = top_level_handle
|
|
296
296
|
self.current_handle = ""
|
|
297
297
|
self.current_parent_handle = ""
|
|
298
298
|
|
|
299
|
-
def switch_to_browsing_context(self, handle):
|
|
299
|
+
async def switch_to_browsing_context(self, handle):
|
|
300
300
|
self.current_handle = handle
|
|
301
301
|
if not self.current_handle:
|
|
302
302
|
self.current_parent_handle = ""
|
|
303
303
|
return
|
|
304
304
|
|
|
305
|
-
resp = self.protocol.resolveParentFrameHandle(
|
|
305
|
+
resp = await self.protocol.resolveParentFrameHandle(
|
|
306
306
|
browsingContextHandle=self.top_level_handle, frameHandle=self.current_handle
|
|
307
307
|
)
|
|
308
308
|
self.current_parent_handle = resp["result"]
|
|
309
309
|
|
|
310
|
-
def switch_to_browsing_context_frame(self, context, frame):
|
|
311
|
-
self.protocol.switchToBrowsingContext(browsingContextHandle=context, frameHandle=frame)
|
|
310
|
+
async def switch_to_browsing_context_frame(self, context, frame):
|
|
311
|
+
await self.protocol.switchToBrowsingContext(browsingContextHandle=context, frameHandle=frame)
|
|
312
312
|
|
|
313
|
-
def navigate_broswing_context(self, url):
|
|
314
|
-
self.protocol.navigateBrowsingContext(
|
|
313
|
+
async def navigate_broswing_context(self, url):
|
|
314
|
+
await self.protocol.navigateBrowsingContext(
|
|
315
315
|
handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout, url=url
|
|
316
316
|
)
|
|
317
317
|
|
|
318
|
-
def go_back_in_browsing_context(self):
|
|
319
|
-
self.protocol.goBackInBrowsingContext(
|
|
318
|
+
async def go_back_in_browsing_context(self):
|
|
319
|
+
await self.protocol.goBackInBrowsingContext(
|
|
320
|
+
handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout
|
|
321
|
+
)
|
|
320
322
|
|
|
321
|
-
def go_forward_in_browsing_context(self):
|
|
322
|
-
self.protocol.goForwardInBrowsingContext(
|
|
323
|
+
async def go_forward_in_browsing_context(self):
|
|
324
|
+
await self.protocol.goForwardInBrowsingContext(
|
|
325
|
+
handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout
|
|
326
|
+
)
|
|
323
327
|
|
|
324
|
-
def reload_browsing_context(self):
|
|
325
|
-
self.protocol.reloadBrowsingContext(handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout)
|
|
328
|
+
async def reload_browsing_context(self):
|
|
329
|
+
await self.protocol.reloadBrowsingContext(handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout)
|
|
326
330
|
|
|
327
|
-
def switch_to_frame(self, frame_ordinal=None, frame_handle=None):
|
|
331
|
+
async def switch_to_frame(self, frame_ordinal=None, frame_handle=None):
|
|
328
332
|
params = {"browsingContextHandle": self.top_level_handle}
|
|
329
333
|
if self.current_handle:
|
|
330
334
|
params["frameHandle"] = self.current_handle
|
|
@@ -332,23 +336,23 @@ class AutomationSession:
|
|
|
332
336
|
params["ordinal"] = frame_ordinal
|
|
333
337
|
elif frame_handle is not None:
|
|
334
338
|
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)
|
|
339
|
+
resp = (await self.protocol.resolveChildFrameHandle(**params))["result"]
|
|
340
|
+
await self.switch_to_browsing_context_frame(self.top_level_handle, resp)
|
|
341
|
+
await self.switch_to_browsing_context(resp)
|
|
338
342
|
|
|
339
|
-
def switch_to_window(self, handle):
|
|
340
|
-
self.switch_to_browsing_context_frame(handle, "")
|
|
341
|
-
self.switch_to_top_level_browsing_context(handle)
|
|
343
|
+
async def switch_to_window(self, handle):
|
|
344
|
+
await self.switch_to_browsing_context_frame(handle, "")
|
|
345
|
+
await self.switch_to_top_level_browsing_context(handle)
|
|
342
346
|
|
|
343
|
-
def perform_keyboard_interactions(self, interactions):
|
|
347
|
+
async def perform_keyboard_interactions(self, interactions):
|
|
344
348
|
for interaction in interactions:
|
|
345
349
|
type_ = interaction["type"]
|
|
346
350
|
interaction["type"] = type_.value if isinstance(type_, KeyboardInteractionType) else type_
|
|
347
|
-
self.protocol.performKeyboardInteractions(handle=self.top_level_handle, interactions=interactions)
|
|
351
|
+
await self.protocol.performKeyboardInteractions(handle=self.top_level_handle, interactions=interactions)
|
|
348
352
|
|
|
349
|
-
def perform_mouse_interaction(self, x, y, button: MouseButton, interaction: MouseInteraction, modifiers=None):
|
|
353
|
+
async def perform_mouse_interaction(self, x, y, button: MouseButton, interaction: MouseInteraction, modifiers=None):
|
|
350
354
|
modifiers = [] if modifiers is None else modifiers
|
|
351
|
-
self.protocol.performMouseInteraction(
|
|
355
|
+
await self.protocol.performMouseInteraction(
|
|
352
356
|
handle=self.top_level_handle,
|
|
353
357
|
position={"x": x, "y": y},
|
|
354
358
|
button=button.value,
|
|
@@ -356,7 +360,7 @@ class AutomationSession:
|
|
|
356
360
|
modifiers=modifiers,
|
|
357
361
|
)
|
|
358
362
|
|
|
359
|
-
def perform_interaction_sequence(self, sources, steps):
|
|
363
|
+
async def perform_interaction_sequence(self, sources, steps):
|
|
360
364
|
params = {
|
|
361
365
|
"handle": self.top_level_handle,
|
|
362
366
|
"inputSources": sources,
|
|
@@ -364,30 +368,32 @@ class AutomationSession:
|
|
|
364
368
|
}
|
|
365
369
|
if self.current_handle:
|
|
366
370
|
params["frameHandle"] = self.current_handle
|
|
367
|
-
self.protocol.performInteractionSequence(**params)
|
|
371
|
+
await self.protocol.performInteractionSequence(**params)
|
|
368
372
|
|
|
369
|
-
def wait_for_navigation_to_complete(self):
|
|
373
|
+
async def wait_for_navigation_to_complete(self):
|
|
370
374
|
params = {"browsingContextHandle": self.top_level_handle, "pageLoadTimeout": self.page_load_timeout}
|
|
371
375
|
if self.current_handle:
|
|
372
376
|
params["frameHandle"] = self.current_handle
|
|
373
|
-
self.protocol.waitForNavigationToComplete(**params)
|
|
377
|
+
await self.protocol.waitForNavigationToComplete(**params)
|
|
374
378
|
|
|
375
|
-
def accept_current_javascript_dialog(self):
|
|
376
|
-
self.protocol.acceptCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)
|
|
379
|
+
async def accept_current_javascript_dialog(self):
|
|
380
|
+
await self.protocol.acceptCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)
|
|
377
381
|
|
|
378
|
-
def dismiss_current_javascript_dialog(self):
|
|
379
|
-
self.protocol.dismissCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)
|
|
382
|
+
async def dismiss_current_javascript_dialog(self):
|
|
383
|
+
await self.protocol.dismissCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)
|
|
380
384
|
|
|
381
|
-
def set_user_input_for_current_javascript_prompt(self, user_input):
|
|
382
|
-
self.protocol.setUserInputForCurrentJavaScriptPrompt(
|
|
385
|
+
async def set_user_input_for_current_javascript_prompt(self, user_input):
|
|
386
|
+
await self.protocol.setUserInputForCurrentJavaScriptPrompt(
|
|
383
387
|
browsingContextHandle=self.top_level_handle, userInput=user_input
|
|
384
388
|
)
|
|
385
389
|
|
|
386
|
-
def message_of_current_javascript_dialog(self):
|
|
387
|
-
return self.protocol.messageOfCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)[
|
|
390
|
+
async def message_of_current_javascript_dialog(self):
|
|
391
|
+
return (await self.protocol.messageOfCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle))[
|
|
392
|
+
"message"
|
|
393
|
+
]
|
|
388
394
|
|
|
389
|
-
def compute_element_layout(self, node_id, scroll_if_needed, coordinate_system):
|
|
390
|
-
return self.protocol.computeElementLayout(
|
|
395
|
+
async def compute_element_layout(self, node_id, scroll_if_needed, coordinate_system):
|
|
396
|
+
return await self.protocol.computeElementLayout(
|
|
391
397
|
browsingContextHandle=self.top_level_handle,
|
|
392
398
|
nodeHandle=node_id,
|
|
393
399
|
scrollIntoViewIfNeeded=scroll_if_needed,
|
|
@@ -395,8 +401,8 @@ class AutomationSession:
|
|
|
395
401
|
frameHandle="" if self.current_handle is None else self.current_handle,
|
|
396
402
|
)
|
|
397
403
|
|
|
398
|
-
def select_option_element(self, node_id):
|
|
399
|
-
self.protocol.selectOptionElement(
|
|
404
|
+
async def select_option_element(self, node_id):
|
|
405
|
+
await self.protocol.selectOptionElement(
|
|
400
406
|
browsingContextHandle=self.top_level_handle,
|
|
401
407
|
nodeHandle=node_id,
|
|
402
408
|
frameHandle="" if self.current_handle is None else self.current_handle,
|