pymobiledevice3 4.27.4__py3-none-any.whl → 5.1.2__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 (143) hide show
  1. misc/plist_sniffer.py +15 -15
  2. misc/remotexpc_sniffer.py +29 -28
  3. pymobiledevice3/__main__.py +123 -98
  4. pymobiledevice3/_version.py +2 -2
  5. pymobiledevice3/bonjour.py +351 -117
  6. pymobiledevice3/ca.py +32 -24
  7. pymobiledevice3/cli/activation.py +7 -7
  8. pymobiledevice3/cli/afc.py +19 -19
  9. pymobiledevice3/cli/amfi.py +4 -4
  10. pymobiledevice3/cli/apps.py +51 -39
  11. pymobiledevice3/cli/backup.py +58 -32
  12. pymobiledevice3/cli/bonjour.py +27 -20
  13. pymobiledevice3/cli/cli_common.py +112 -81
  14. pymobiledevice3/cli/companion_proxy.py +4 -4
  15. pymobiledevice3/cli/completions.py +10 -10
  16. pymobiledevice3/cli/crash.py +37 -31
  17. pymobiledevice3/cli/developer.py +601 -519
  18. pymobiledevice3/cli/diagnostics.py +38 -33
  19. pymobiledevice3/cli/lockdown.py +82 -72
  20. pymobiledevice3/cli/mounter.py +84 -67
  21. pymobiledevice3/cli/notification.py +10 -10
  22. pymobiledevice3/cli/pcap.py +19 -14
  23. pymobiledevice3/cli/power_assertion.py +12 -10
  24. pymobiledevice3/cli/processes.py +10 -10
  25. pymobiledevice3/cli/profile.py +88 -77
  26. pymobiledevice3/cli/provision.py +17 -17
  27. pymobiledevice3/cli/remote.py +188 -111
  28. pymobiledevice3/cli/restore.py +43 -40
  29. pymobiledevice3/cli/springboard.py +30 -28
  30. pymobiledevice3/cli/syslog.py +85 -58
  31. pymobiledevice3/cli/usbmux.py +21 -20
  32. pymobiledevice3/cli/version.py +3 -2
  33. pymobiledevice3/cli/webinspector.py +156 -78
  34. pymobiledevice3/common.py +1 -1
  35. pymobiledevice3/exceptions.py +154 -60
  36. pymobiledevice3/irecv.py +49 -53
  37. pymobiledevice3/irecv_devices.py +1489 -492
  38. pymobiledevice3/lockdown.py +400 -251
  39. pymobiledevice3/lockdown_service_provider.py +5 -7
  40. pymobiledevice3/osu/os_utils.py +18 -9
  41. pymobiledevice3/osu/posix_util.py +28 -15
  42. pymobiledevice3/osu/win_util.py +14 -8
  43. pymobiledevice3/pair_records.py +19 -19
  44. pymobiledevice3/remote/common.py +4 -4
  45. pymobiledevice3/remote/core_device/app_service.py +94 -67
  46. pymobiledevice3/remote/core_device/core_device_service.py +17 -14
  47. pymobiledevice3/remote/core_device/device_info.py +5 -5
  48. pymobiledevice3/remote/core_device/diagnostics_service.py +10 -8
  49. pymobiledevice3/remote/core_device/file_service.py +47 -33
  50. pymobiledevice3/remote/remote_service_discovery.py +53 -35
  51. pymobiledevice3/remote/remotexpc.py +64 -42
  52. pymobiledevice3/remote/tunnel_service.py +383 -297
  53. pymobiledevice3/remote/utils.py +14 -13
  54. pymobiledevice3/remote/xpc_message.py +145 -125
  55. pymobiledevice3/resources/dsc_uuid_map.py +19 -19
  56. pymobiledevice3/resources/firmware_notifications.py +16 -16
  57. pymobiledevice3/restore/asr.py +27 -27
  58. pymobiledevice3/restore/base_restore.py +90 -47
  59. pymobiledevice3/restore/consts.py +87 -66
  60. pymobiledevice3/restore/device.py +11 -11
  61. pymobiledevice3/restore/fdr.py +46 -46
  62. pymobiledevice3/restore/ftab.py +19 -19
  63. pymobiledevice3/restore/img4.py +130 -133
  64. pymobiledevice3/restore/mbn.py +587 -0
  65. pymobiledevice3/restore/recovery.py +125 -135
  66. pymobiledevice3/restore/restore.py +535 -523
  67. pymobiledevice3/restore/restore_options.py +122 -115
  68. pymobiledevice3/restore/restored_client.py +25 -22
  69. pymobiledevice3/restore/tss.py +378 -270
  70. pymobiledevice3/service_connection.py +50 -46
  71. pymobiledevice3/services/accessibilityaudit.py +137 -127
  72. pymobiledevice3/services/afc.py +352 -292
  73. pymobiledevice3/services/amfi.py +21 -18
  74. pymobiledevice3/services/companion.py +23 -19
  75. pymobiledevice3/services/crash_reports.py +61 -47
  76. pymobiledevice3/services/debugserver_applist.py +3 -3
  77. pymobiledevice3/services/device_arbitration.py +8 -8
  78. pymobiledevice3/services/device_link.py +56 -48
  79. pymobiledevice3/services/diagnostics.py +971 -968
  80. pymobiledevice3/services/dtfetchsymbols.py +8 -8
  81. pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +4 -4
  82. pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +4 -4
  83. pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +85 -74
  84. pymobiledevice3/services/dvt/instruments/application_listing.py +2 -3
  85. pymobiledevice3/services/dvt/instruments/condition_inducer.py +7 -6
  86. pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +466 -384
  87. pymobiledevice3/services/dvt/instruments/device_info.py +11 -11
  88. pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
  89. pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
  90. pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
  91. pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
  92. pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
  93. pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
  94. pymobiledevice3/services/dvt/instruments/process_control.py +25 -10
  95. pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
  96. pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
  97. pymobiledevice3/services/dvt/testmanaged/xcuitest.py +42 -52
  98. pymobiledevice3/services/file_relay.py +10 -10
  99. pymobiledevice3/services/heartbeat.py +8 -7
  100. pymobiledevice3/services/house_arrest.py +12 -15
  101. pymobiledevice3/services/installation_proxy.py +119 -100
  102. pymobiledevice3/services/lockdown_service.py +12 -5
  103. pymobiledevice3/services/misagent.py +22 -19
  104. pymobiledevice3/services/mobile_activation.py +84 -72
  105. pymobiledevice3/services/mobile_config.py +331 -301
  106. pymobiledevice3/services/mobile_image_mounter.py +137 -116
  107. pymobiledevice3/services/mobilebackup2.py +188 -150
  108. pymobiledevice3/services/notification_proxy.py +11 -11
  109. pymobiledevice3/services/os_trace.py +128 -74
  110. pymobiledevice3/services/pcapd.py +306 -306
  111. pymobiledevice3/services/power_assertion.py +10 -9
  112. pymobiledevice3/services/preboard.py +4 -4
  113. pymobiledevice3/services/remote_fetch_symbols.py +16 -14
  114. pymobiledevice3/services/remote_server.py +176 -146
  115. pymobiledevice3/services/restore_service.py +16 -16
  116. pymobiledevice3/services/screenshot.py +13 -10
  117. pymobiledevice3/services/simulate_location.py +7 -7
  118. pymobiledevice3/services/springboard.py +15 -15
  119. pymobiledevice3/services/syslog.py +5 -5
  120. pymobiledevice3/services/web_protocol/alert.py +3 -3
  121. pymobiledevice3/services/web_protocol/automation_session.py +183 -179
  122. pymobiledevice3/services/web_protocol/cdp_screencast.py +44 -36
  123. pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
  124. pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
  125. pymobiledevice3/services/web_protocol/driver.py +47 -45
  126. pymobiledevice3/services/web_protocol/element.py +74 -63
  127. pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
  128. pymobiledevice3/services/web_protocol/selenium_api.py +3 -3
  129. pymobiledevice3/services/web_protocol/session_protocol.py +15 -10
  130. pymobiledevice3/services/web_protocol/switch_to.py +11 -12
  131. pymobiledevice3/services/webinspector.py +142 -116
  132. pymobiledevice3/tcp_forwarder.py +35 -22
  133. pymobiledevice3/tunneld/api.py +20 -15
  134. pymobiledevice3/tunneld/server.py +310 -193
  135. pymobiledevice3/usbmux.py +197 -148
  136. pymobiledevice3/utils.py +14 -11
  137. {pymobiledevice3-4.27.4.dist-info → pymobiledevice3-5.1.2.dist-info}/METADATA +1 -2
  138. pymobiledevice3-5.1.2.dist-info/RECORD +173 -0
  139. pymobiledevice3-4.27.4.dist-info/RECORD +0 -172
  140. {pymobiledevice3-4.27.4.dist-info → pymobiledevice3-5.1.2.dist-info}/WHEEL +0 -0
  141. {pymobiledevice3-4.27.4.dist-info → pymobiledevice3-5.1.2.dist-info}/entry_points.txt +0 -0
  142. {pymobiledevice3-4.27.4.dist-info → pymobiledevice3-5.1.2.dist-info}/licenses/LICENSE +0 -0
  143. {pymobiledevice3-4.27.4.dist-info → pymobiledevice3-5.1.2.dist-info}/top_level.txt +0 -0
@@ -3,129 +3,130 @@ from dataclasses import dataclass
3
3
  from enum import Enum
4
4
  from pathlib import Path
5
5
 
6
- RESOURCES = Path(__file__).parent.parent.parent / 'resources' / 'webinspector'
7
- FIND_NODES = (RESOURCES / 'find_nodes.js').read_text()
6
+ RESOURCES = Path(__file__).parent.parent.parent / "resources" / "webinspector"
7
+ FIND_NODES = (RESOURCES / "find_nodes.js").read_text()
8
8
 
9
9
 
10
10
  class By(Enum):
11
11
  """
12
12
  Set of supported locator strategies.
13
13
  """
14
- ID = 'id'
15
- XPATH = 'xpath'
16
- LINK_TEXT = 'link text'
17
- PARTIAL_LINK_TEXT = 'partial link text'
18
- NAME = 'name'
19
- TAG_NAME = 'tag name'
20
- CLASS_NAME = 'class name'
21
- CSS_SELECTOR = 'css selector'
14
+
15
+ ID = "id"
16
+ XPATH = "xpath"
17
+ LINK_TEXT = "link text"
18
+ PARTIAL_LINK_TEXT = "partial link text"
19
+ NAME = "name"
20
+ TAG_NAME = "tag name"
21
+ CLASS_NAME = "class name"
22
+ CSS_SELECTOR = "css selector"
22
23
 
23
24
 
24
25
  class MouseButton(Enum):
25
- NONE = 'None'
26
- LEFT = 'Left'
27
- MIDDLE = 'Middle'
28
- RIGHT = 'Right'
26
+ NONE = "None"
27
+ LEFT = "Left"
28
+ MIDDLE = "Middle"
29
+ RIGHT = "Right"
29
30
 
30
31
 
31
32
  class MouseInteraction(Enum):
32
- MOVE = 'Move'
33
- DOWN = 'Down'
34
- UP = 'Up'
35
- SINGLE_CLICK = 'SingleClick'
36
- DOUBLE_CLICK = 'DoubleClick'
33
+ MOVE = "Move"
34
+ DOWN = "Down"
35
+ UP = "Up"
36
+ SINGLE_CLICK = "SingleClick"
37
+ DOUBLE_CLICK = "DoubleClick"
37
38
 
38
39
 
39
40
  class KeyboardInteractionType(Enum):
40
- KEY_PRESS = 'KeyPress'
41
- KEY_RELEASE = 'KeyRelease'
42
- INSERT_BY_KEY = 'InsertByKey'
41
+ KEY_PRESS = "KeyPress"
42
+ KEY_RELEASE = "KeyRelease"
43
+ INSERT_BY_KEY = "InsertByKey"
43
44
 
44
45
 
45
46
  class KeyModifier(Enum):
46
- CAPS_LOCK = 'CapsLock'
47
- CONTROL = 'Control'
48
- SHIFT = 'Shift'
49
- META = 'Meta'
50
- ALT = 'Alt'
47
+ CAPS_LOCK = "CapsLock"
48
+ CONTROL = "Control"
49
+ SHIFT = "Shift"
50
+ META = "Meta"
51
+ ALT = "Alt"
51
52
 
52
53
 
53
54
  VIRTUAL_KEYS = {
54
- '\ue001': ('Cancel', None),
55
- '\ue002': ('Help', None),
56
- '\ue003': ('Backspace', None),
57
- '\ue004': ('Tab', None),
58
- '\ue005': ('Clear', None),
59
- '\ue006': ('Return', None),
60
- '\ue007': ('Enter', None),
61
- '\ue008': ('Shift', KeyModifier.SHIFT),
62
- '\ue050': ('Shift', KeyModifier.SHIFT),
63
- '\ue009': ('Control', KeyModifier.CONTROL),
64
- '\ue051': ('Control', KeyModifier.CONTROL),
65
- '\ue00a': ('Alternate', KeyModifier.ALT),
66
- '\ue052': ('Alternate', KeyModifier.ALT),
67
- '\ue00b': ('Pause', None),
68
- '\ue00c': ('Escape', None),
69
- '\ue00d': ('Space', None),
70
- '\ue00e': ('PageUp', None),
71
- '\ue054': ('PageUp', None),
72
- '\ue00f': ('PageDown', None),
73
- '\ue055': ('PageDown', None),
74
- '\ue010': ('End', None),
75
- '\ue056': ('End', None),
76
- '\ue011': ('Home', None),
77
- '\ue057': ('Home', None),
78
- '\ue012': ('LeftArrow', None),
79
- '\ue058': ('LeftArrow', None),
80
- '\ue013': ('UpArrow', None),
81
- '\ue059': ('UpArrow', None),
82
- '\ue014': ('RightArrow', None),
83
- '\ue05a': ('RightArrow', None),
84
- '\ue015': ('DownArrow', None),
85
- '\ue05b': ('DownArrow', None),
86
- '\ue016': ('Insert', None),
87
- '\ue05c': ('Insert', None),
88
- '\ue017': ('Delete', None),
89
- '\ue05d': ('Delete', None),
90
- '\ue018': ('Semicolon', None),
91
- '\ue019': ('Equals', None),
92
- '\ue01a': ('NumberPad0', None),
93
- '\ue01b': ('NumberPad1', None),
94
- '\ue01c': ('NumberPad2', None),
95
- '\ue01d': ('NumberPad3', None),
96
- '\ue01e': ('NumberPad4', None),
97
- '\ue01f': ('NumberPad5', None),
98
- '\ue020': ('NumberPad6', None),
99
- '\ue021': ('NumberPad7', None),
100
- '\ue022': ('NumberPad8', None),
101
- '\ue023': ('NumberPad9', None),
102
- '\ue024': ('NumberPadMultiply', None),
103
- '\ue025': ('NumberPadAdd', None),
104
- '\ue026': ('NumberPadSeparator', None),
105
- '\ue027': ('NumberPadSubtract', None),
106
- '\ue028': ('NumberPadDecimal', None),
107
- '\ue029': ('NumberPadDivide', None),
108
- '\ue031': ('Function1', None),
109
- '\ue032': ('Function2', None),
110
- '\ue033': ('Function3', None),
111
- '\ue034': ('Function4', None),
112
- '\ue035': ('Function5', None),
113
- '\ue036': ('Function6', None),
114
- '\ue037': ('Function7', None),
115
- '\ue038': ('Function8', None),
116
- '\ue039': ('Function9', None),
117
- '\ue03a': ('Function10', None),
118
- '\ue03b': ('Function11', None),
119
- '\ue03c': ('Function12', None),
120
- '\ue03d': ('Meta', KeyModifier.META),
121
- '\ue053': ('Meta', KeyModifier.META),
55
+ "\ue001": ("Cancel", None),
56
+ "\ue002": ("Help", None),
57
+ "\ue003": ("Backspace", None),
58
+ "\ue004": ("Tab", None),
59
+ "\ue005": ("Clear", None),
60
+ "\ue006": ("Return", None),
61
+ "\ue007": ("Enter", None),
62
+ "\ue008": ("Shift", KeyModifier.SHIFT),
63
+ "\ue050": ("Shift", KeyModifier.SHIFT),
64
+ "\ue009": ("Control", KeyModifier.CONTROL),
65
+ "\ue051": ("Control", KeyModifier.CONTROL),
66
+ "\ue00a": ("Alternate", KeyModifier.ALT),
67
+ "\ue052": ("Alternate", KeyModifier.ALT),
68
+ "\ue00b": ("Pause", None),
69
+ "\ue00c": ("Escape", None),
70
+ "\ue00d": ("Space", None),
71
+ "\ue00e": ("PageUp", None),
72
+ "\ue054": ("PageUp", None),
73
+ "\ue00f": ("PageDown", None),
74
+ "\ue055": ("PageDown", None),
75
+ "\ue010": ("End", None),
76
+ "\ue056": ("End", None),
77
+ "\ue011": ("Home", None),
78
+ "\ue057": ("Home", None),
79
+ "\ue012": ("LeftArrow", None),
80
+ "\ue058": ("LeftArrow", None),
81
+ "\ue013": ("UpArrow", None),
82
+ "\ue059": ("UpArrow", None),
83
+ "\ue014": ("RightArrow", None),
84
+ "\ue05a": ("RightArrow", None),
85
+ "\ue015": ("DownArrow", None),
86
+ "\ue05b": ("DownArrow", None),
87
+ "\ue016": ("Insert", None),
88
+ "\ue05c": ("Insert", None),
89
+ "\ue017": ("Delete", None),
90
+ "\ue05d": ("Delete", None),
91
+ "\ue018": ("Semicolon", None),
92
+ "\ue019": ("Equals", None),
93
+ "\ue01a": ("NumberPad0", None),
94
+ "\ue01b": ("NumberPad1", None),
95
+ "\ue01c": ("NumberPad2", None),
96
+ "\ue01d": ("NumberPad3", None),
97
+ "\ue01e": ("NumberPad4", None),
98
+ "\ue01f": ("NumberPad5", None),
99
+ "\ue020": ("NumberPad6", None),
100
+ "\ue021": ("NumberPad7", None),
101
+ "\ue022": ("NumberPad8", None),
102
+ "\ue023": ("NumberPad9", None),
103
+ "\ue024": ("NumberPadMultiply", None),
104
+ "\ue025": ("NumberPadAdd", None),
105
+ "\ue026": ("NumberPadSeparator", None),
106
+ "\ue027": ("NumberPadSubtract", None),
107
+ "\ue028": ("NumberPadDecimal", None),
108
+ "\ue029": ("NumberPadDivide", None),
109
+ "\ue031": ("Function1", None),
110
+ "\ue032": ("Function2", None),
111
+ "\ue033": ("Function3", None),
112
+ "\ue034": ("Function4", None),
113
+ "\ue035": ("Function5", None),
114
+ "\ue036": ("Function6", None),
115
+ "\ue037": ("Function7", None),
116
+ "\ue038": ("Function8", None),
117
+ "\ue039": ("Function9", None),
118
+ "\ue03a": ("Function10", None),
119
+ "\ue03b": ("Function11", None),
120
+ "\ue03c": ("Function12", None),
121
+ "\ue03d": ("Meta", KeyModifier.META),
122
+ "\ue053": ("Meta", KeyModifier.META),
122
123
  }
123
124
 
124
125
  MODIFIER_TO_KEY = {
125
- KeyModifier.SHIFT: 'Shift',
126
- KeyModifier.CONTROL: 'Control',
127
- KeyModifier.ALT: 'Alternate',
128
- KeyModifier.META: 'Meta',
126
+ KeyModifier.SHIFT: "Shift",
127
+ KeyModifier.CONTROL: "Control",
128
+ KeyModifier.ALT: "Alternate",
129
+ KeyModifier.META: "Meta",
129
130
  }
130
131
 
131
132
 
@@ -155,9 +156,9 @@ class AutomationSession:
155
156
  :param pymobiledevice3.services.web_protocol.session_protocol.SessionProtocol protocol: Session protocol.
156
157
  """
157
158
  self.protocol = protocol
158
- self.top_level_handle = ''
159
- self.current_handle = ''
160
- self.current_parent_handle = ''
159
+ self.top_level_handle = ""
160
+ self.current_handle = ""
161
+ self.current_parent_handle = ""
161
162
  self.implicit_wait_timeout = 0
162
163
  self.page_load_timeout = 3000000
163
164
  self.script_timeout = -1
@@ -167,20 +168,20 @@ class AutomationSession:
167
168
  return self.protocol.id_
168
169
 
169
170
  def start_session(self):
170
- handle = self.protocol.createBrowsingContext()['handle']
171
+ handle = self.protocol.createBrowsingContext()["handle"]
171
172
  self.switch_to_top_level_browsing_context(handle)
172
173
 
173
174
  def stop_session(self):
174
- self.top_level_handle = ''
175
- self.current_handle = ''
176
- self.current_parent_handle = ''
175
+ self.top_level_handle = ""
176
+ self.current_handle = ""
177
+ self.current_parent_handle = ""
177
178
  for handle in self.get_window_handles():
178
179
  self.protocol.closeBrowsingContext(handle=handle)
179
180
 
180
181
  def create_window(self, type_):
181
182
  type_ = type_.capitalize()
182
- params = {'presentationHint': type_} if type_ else {}
183
- return self.protocol.createBrowsingContext(**params)['handle']
183
+ params = {"presentationHint": type_} if type_ else {}
184
+ return self.protocol.createBrowsingContext(**params)["handle"]
184
185
 
185
186
  def close_window(self):
186
187
  if not self.top_level_handle:
@@ -195,18 +196,18 @@ class AutomationSession:
195
196
  self.protocol.hideWindowOfBrowsingContext(handle=self.top_level_handle)
196
197
 
197
198
  def get_browsing_context(self):
198
- return self.protocol.getBrowsingContext(handle=self.top_level_handle)['context']
199
+ return self.protocol.getBrowsingContext(handle=self.top_level_handle)["context"]
199
200
 
200
201
  def get_window_handles(self):
201
202
  contexts = self.protocol.getBrowsingContexts()
202
- return [c['handle'] for c in contexts['contexts']]
203
+ return [c["handle"] for c in contexts["contexts"]]
203
204
 
204
205
  def set_window_frame(self, x=None, y=None, width=None, height=None):
205
206
  params = {}
206
207
  if x is not None and y is not None:
207
- params['origin'] = {'x': x, 'y': y}
208
+ params["origin"] = {"x": x, "y": y}
208
209
  if width is not None and height is not None:
209
- params['size'] = {'width': width, 'height': height}
210
+ params["size"] = {"width": width, "height": height}
210
211
  self.protocol.setWindowFrameOfBrowsingContext(handle=self.top_level_handle, **params)
211
212
 
212
213
  def add_single_cookie(self, cookie):
@@ -219,91 +220,92 @@ class AutomationSession:
219
220
  self.protocol.deleteSingleCookie(browsingContextHandle=self.top_level_handle, cookieName=name)
220
221
 
221
222
  def get_all_cookies(self):
222
- return self.protocol.getAllCookies(browsingContextHandle=self.top_level_handle)['cookies']
223
+ return self.protocol.getAllCookies(browsingContextHandle=self.top_level_handle)["cookies"]
223
224
 
224
225
  def execute_script(self, script, args, async_=False):
225
226
  parameters = {
226
- 'browsingContextHandle': self.top_level_handle,
227
- 'function': 'function(){\n' + script + '\n}',
228
- 'arguments': list(map(json.dumps, args)),
227
+ "browsingContextHandle": self.top_level_handle,
228
+ "function": "function(){\n" + script + "\n}",
229
+ "arguments": list(map(json.dumps, args)),
229
230
  }
230
231
  if self.current_handle:
231
- parameters['frameHandle'] = self.current_handle
232
+ parameters["frameHandle"] = self.current_handle
232
233
  if async_:
233
- parameters['expectsImplicitCallbackArgument'] = True
234
+ parameters["expectsImplicitCallbackArgument"] = True
234
235
  if self.script_timeout != -1:
235
- parameters['callbackTimeout'] = self.script_timeout
236
+ parameters["callbackTimeout"] = self.script_timeout
236
237
  result = self.protocol.evaluateJavaScriptFunction(**parameters, wait_for_response=not async_)
237
238
  if async_:
238
239
  return result
239
240
  else:
240
- return json.loads(result['result'])
241
+ return json.loads(result["result"])
241
242
 
242
243
  def evaluate_js_function(self, function, *args, implicit_callback=False, include_frame=True):
243
244
  params = {
244
- 'browsingContextHandle': self.top_level_handle,
245
- 'function': function,
246
- 'arguments': list(map(json.dumps, args)),
245
+ "browsingContextHandle": self.top_level_handle,
246
+ "function": function,
247
+ "arguments": list(map(json.dumps, args)),
247
248
  }
248
249
  if include_frame and self.current_handle:
249
- params['frameHandle'] = self.current_handle
250
+ params["frameHandle"] = self.current_handle
250
251
  if implicit_callback:
251
- params['expectsImplicitCallbackArgument'] = True
252
+ params["expectsImplicitCallbackArgument"] = True
252
253
  result = self.protocol.evaluateJavaScriptFunction(**params)
253
- return json.loads(result['result'])
254
+ return json.loads(result["result"])
254
255
 
255
256
  def find_elements(self, by, value, single: bool = True, root=None):
256
257
  self.wait_for_navigation_to_complete()
257
258
  by = by.value if isinstance(by, By) else by
258
259
  if by == By.ID.value:
259
260
  by = By.CSS_SELECTOR.value
260
- value = '[id="%s"]' % value
261
+ value = f'[id="{value}"]'
261
262
  elif by == By.TAG_NAME.value:
262
263
  by = By.CSS_SELECTOR.value
263
264
  elif by == By.CLASS_NAME.value:
264
265
  by = By.CSS_SELECTOR.value
265
- value = ".%s" % value
266
+ value = f".{value}"
266
267
  elif by == By.NAME.value:
267
268
  by = By.CSS_SELECTOR.value
268
- value = '[name="%s"]' % value
269
+ value = f'[name="{value}"]'
269
270
 
270
271
  parameters = {
271
- 'browsingContextHandle': self.top_level_handle,
272
- 'function': FIND_NODES,
273
- 'arguments': list(map(json.dumps, [by, root, value, single, self.implicit_wait_timeout])),
274
- 'expectsImplicitCallbackArgument': True,
272
+ "browsingContextHandle": self.top_level_handle,
273
+ "function": FIND_NODES,
274
+ "arguments": list(map(json.dumps, [by, root, value, single, self.implicit_wait_timeout])),
275
+ "expectsImplicitCallbackArgument": True,
275
276
  }
276
277
  if self.current_handle:
277
- parameters['frameHandle'] = self.current_handle
278
+ parameters["frameHandle"] = self.current_handle
278
279
  if self.implicit_wait_timeout:
279
- parameters['callbackTimeout'] = self.implicit_wait_timeout + 1000
280
- result = json.loads(self.protocol.evaluateJavaScriptFunction(**parameters)['result'])
280
+ parameters["callbackTimeout"] = self.implicit_wait_timeout + 1000
281
+ result = json.loads(self.protocol.evaluateJavaScriptFunction(**parameters)["result"])
281
282
  return result
282
283
 
283
- def screenshot_as_base64(self, scroll=False, node_id='', clip=True):
284
- params = {'handle': self.top_level_handle, 'clipToViewport': clip}
284
+ def screenshot_as_base64(self, scroll=False, node_id="", clip=True):
285
+ params = {"handle": self.top_level_handle, "clipToViewport": clip}
285
286
  if self.current_handle:
286
- params['frameHandle'] = self.current_handle
287
+ params["frameHandle"] = self.current_handle
287
288
  if scroll:
288
- params['scrollIntoViewIfNeeded'] = True
289
+ params["scrollIntoViewIfNeeded"] = True
289
290
  if node_id:
290
- params['nodeHandle'] = node_id
291
- return self.protocol.takeScreenshot(**params)['data']
291
+ params["nodeHandle"] = node_id
292
+ return self.protocol.takeScreenshot(**params)["data"]
292
293
 
293
294
  def switch_to_top_level_browsing_context(self, top_level_handle):
294
295
  self.top_level_handle = top_level_handle
295
- self.current_handle = ''
296
- self.current_parent_handle = ''
296
+ self.current_handle = ""
297
+ self.current_parent_handle = ""
297
298
 
298
299
  def switch_to_browsing_context(self, handle):
299
300
  self.current_handle = handle
300
301
  if not self.current_handle:
301
- self.current_parent_handle = ''
302
+ self.current_parent_handle = ""
302
303
  return
303
304
 
304
- resp = self.protocol.resolveParentFrameHandle(browsingContextHandle=self.top_level_handle,
305
- frameHandle=self.current_handle)
306
- self.current_parent_handle = resp['result']
305
+ resp = self.protocol.resolveParentFrameHandle(
306
+ browsingContextHandle=self.top_level_handle, frameHandle=self.current_handle
307
+ )
308
+ self.current_parent_handle = resp["result"]
307
309
 
308
310
  def switch_to_browsing_context_frame(self, context, frame):
309
311
  self.protocol.switchToBrowsingContext(browsingContextHandle=context, frameHandle=frame)
@@ -314,61 +316,60 @@ class AutomationSession:
314
316
  )
315
317
 
316
318
  def go_back_in_browsing_context(self):
317
- self.protocol.goBackInBrowsingContext(
318
- handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout
319
- )
319
+ self.protocol.goBackInBrowsingContext(handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout)
320
320
 
321
321
  def go_forward_in_browsing_context(self):
322
- self.protocol.goForwardInBrowsingContext(
323
- handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout
324
- )
322
+ self.protocol.goForwardInBrowsingContext(handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout)
325
323
 
326
324
  def reload_browsing_context(self):
327
- self.protocol.reloadBrowsingContext(
328
- handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout
329
- )
325
+ self.protocol.reloadBrowsingContext(handle=self.top_level_handle, pageLoadTimeout=self.page_load_timeout)
330
326
 
331
327
  def switch_to_frame(self, frame_ordinal=None, frame_handle=None):
332
- params = {'browsingContextHandle': self.top_level_handle}
328
+ params = {"browsingContextHandle": self.top_level_handle}
333
329
  if self.current_handle:
334
- params['frameHandle'] = self.current_handle
330
+ params["frameHandle"] = self.current_handle
335
331
  if frame_ordinal is not None:
336
- params['ordinal'] = frame_ordinal
332
+ params["ordinal"] = frame_ordinal
337
333
  elif frame_handle is not None:
338
- params['nodeHandle'] = frame_handle.node_id
339
- resp = self.protocol.resolveChildFrameHandle(**params)['result']
334
+ params["nodeHandle"] = frame_handle.node_id
335
+ resp = self.protocol.resolveChildFrameHandle(**params)["result"]
340
336
  self.switch_to_browsing_context_frame(self.top_level_handle, resp)
341
337
  self.switch_to_browsing_context(resp)
342
338
 
343
339
  def switch_to_window(self, handle):
344
- self.switch_to_browsing_context_frame(handle, '')
340
+ self.switch_to_browsing_context_frame(handle, "")
345
341
  self.switch_to_top_level_browsing_context(handle)
346
342
 
347
343
  def perform_keyboard_interactions(self, interactions):
348
344
  for interaction in interactions:
349
- type_ = interaction['type']
350
- interaction['type'] = type_.value if isinstance(type_, KeyboardInteractionType) else type_
345
+ type_ = interaction["type"]
346
+ interaction["type"] = type_.value if isinstance(type_, KeyboardInteractionType) else type_
351
347
  self.protocol.performKeyboardInteractions(handle=self.top_level_handle, interactions=interactions)
352
348
 
353
349
  def perform_mouse_interaction(self, x, y, button: MouseButton, interaction: MouseInteraction, modifiers=None):
354
350
  modifiers = [] if modifiers is None else modifiers
355
- self.protocol.performMouseInteraction(handle=self.top_level_handle, position={'x': x, 'y': y},
356
- button=button.value, interaction=interaction.value, modifiers=modifiers)
351
+ self.protocol.performMouseInteraction(
352
+ handle=self.top_level_handle,
353
+ position={"x": x, "y": y},
354
+ button=button.value,
355
+ interaction=interaction.value,
356
+ modifiers=modifiers,
357
+ )
357
358
 
358
359
  def perform_interaction_sequence(self, sources, steps):
359
360
  params = {
360
- 'handle': self.top_level_handle,
361
- 'inputSources': sources,
362
- 'steps': steps,
361
+ "handle": self.top_level_handle,
362
+ "inputSources": sources,
363
+ "steps": steps,
363
364
  }
364
365
  if self.current_handle:
365
- params['frameHandle'] = self.current_handle
366
+ params["frameHandle"] = self.current_handle
366
367
  self.protocol.performInteractionSequence(**params)
367
368
 
368
369
  def wait_for_navigation_to_complete(self):
369
- params = {'browsingContextHandle': self.top_level_handle, 'pageLoadTimeout': self.page_load_timeout}
370
+ params = {"browsingContextHandle": self.top_level_handle, "pageLoadTimeout": self.page_load_timeout}
370
371
  if self.current_handle:
371
- params['frameHandle'] = self.current_handle
372
+ params["frameHandle"] = self.current_handle
372
373
  self.protocol.waitForNavigationToComplete(**params)
373
374
 
374
375
  def accept_current_javascript_dialog(self):
@@ -383,17 +384,20 @@ class AutomationSession:
383
384
  )
384
385
 
385
386
  def message_of_current_javascript_dialog(self):
386
- return self.protocol.messageOfCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)['message']
387
+ return self.protocol.messageOfCurrentJavaScriptDialog(browsingContextHandle=self.top_level_handle)["message"]
387
388
 
388
389
  def compute_element_layout(self, node_id, scroll_if_needed, coordinate_system):
389
390
  return self.protocol.computeElementLayout(
390
- browsingContextHandle=self.top_level_handle, nodeHandle=node_id,
391
- scrollIntoViewIfNeeded=scroll_if_needed, coordinateSystem=coordinate_system,
392
- frameHandle='' if self.current_handle is None else self.current_handle
391
+ browsingContextHandle=self.top_level_handle,
392
+ nodeHandle=node_id,
393
+ scrollIntoViewIfNeeded=scroll_if_needed,
394
+ coordinateSystem=coordinate_system,
395
+ frameHandle="" if self.current_handle is None else self.current_handle,
393
396
  )
394
397
 
395
398
  def select_option_element(self, node_id):
396
399
  self.protocol.selectOptionElement(
397
- browsingContextHandle=self.top_level_handle, nodeHandle=node_id,
398
- frameHandle='' if self.current_handle is None else self.current_handle
400
+ browsingContextHandle=self.top_level_handle,
401
+ nodeHandle=node_id,
402
+ frameHandle="" if self.current_handle is None else self.current_handle,
399
403
  )