pymobiledevice3 5.0.1__py3-none-any.whl → 5.0.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.

Potentially problematic release.


This version of pymobiledevice3 might be problematic. Click here for more details.

Files changed (143) hide show
  1. misc/plist_sniffer.py +15 -15
  2. misc/remotexpc_sniffer.py +29 -28
  3. pymobiledevice3/__main__.py +128 -102
  4. pymobiledevice3/_version.py +2 -2
  5. pymobiledevice3/bonjour.py +26 -49
  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 +25 -18
  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 +602 -520
  18. pymobiledevice3/cli/diagnostics.py +38 -33
  19. pymobiledevice3/cli/lockdown.py +79 -74
  20. pymobiledevice3/cli/mounter.py +85 -68
  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 +186 -110
  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 +157 -79
  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 +394 -241
  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 +62 -41
  52. pymobiledevice3/remote/tunnel_service.py +371 -293
  53. pymobiledevice3/remote/utils.py +12 -11
  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 +35 -54
  65. pymobiledevice3/restore/recovery.py +125 -135
  66. pymobiledevice3/restore/restore.py +524 -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 +136 -126
  72. pymobiledevice3/services/afc.py +350 -291
  73. pymobiledevice3/services/amfi.py +21 -18
  74. pymobiledevice3/services/companion.py +23 -19
  75. pymobiledevice3/services/crash_reports.py +60 -46
  76. pymobiledevice3/services/debugserver_applist.py +3 -3
  77. pymobiledevice3/services/device_arbitration.py +8 -8
  78. pymobiledevice3/services/device_link.py +55 -47
  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 +442 -421
  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 +40 -50
  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 +330 -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 +69 -51
  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 +180 -176
  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 +2 -2
  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 +127 -116
  132. pymobiledevice3/tcp_forwarder.py +35 -22
  133. pymobiledevice3/tunneld/api.py +20 -15
  134. pymobiledevice3/tunneld/server.py +212 -133
  135. pymobiledevice3/usbmux.py +183 -138
  136. pymobiledevice3/utils.py +14 -11
  137. {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.2.dist-info}/METADATA +1 -1
  138. pymobiledevice3-5.0.2.dist-info/RECORD +173 -0
  139. pymobiledevice3-5.0.1.dist-info/RECORD +0 -173
  140. {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.2.dist-info}/WHEEL +0 -0
  141. {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.2.dist-info}/entry_points.txt +0 -0
  142. {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.2.dist-info}/licenses/LICENSE +0 -0
  143. {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.2.dist-info}/top_level.txt +0 -0
@@ -8,15 +8,15 @@ from pymobiledevice3.exceptions import InspectorEvaluateError
8
8
  from pymobiledevice3.services.web_protocol.session_protocol import SessionProtocol
9
9
 
10
10
  logger = logging.getLogger(__name__)
11
- console_logger = logging.getLogger('webinspector.console')
12
- heap_logger = logging.getLogger('webinspector.heap')
11
+ console_logger = logging.getLogger("webinspector.console")
12
+ heap_logger = logging.getLogger("webinspector.heap")
13
13
 
14
14
  webinspector_logger_handlers = {
15
- 'log': console_logger.info,
16
- 'info': console_logger.info,
17
- 'error': console_logger.error,
18
- 'debug': console_logger.debug,
19
- 'warning': console_logger.warning,
15
+ "log": console_logger.info,
16
+ "info": console_logger.info,
17
+ "error": console_logger.error,
18
+ "debug": console_logger.debug,
19
+ "warning": console_logger.warning,
20
20
  }
21
21
 
22
22
 
@@ -24,8 +24,8 @@ class JSObjectPreview(UserDict):
24
24
  def __init__(self, properties: list[dict]):
25
25
  super().__init__()
26
26
  for p in properties:
27
- name = p['name']
28
- value = p['value']
27
+ name = p["name"]
28
+ value = p["value"]
29
29
  self.data[name] = value
30
30
 
31
31
 
@@ -33,26 +33,25 @@ class JSObjectProperties(UserDict):
33
33
  def __init__(self, properties: list[dict]):
34
34
  super().__init__()
35
35
  for p in properties:
36
- name = p['name']
37
- if name == '__proto__':
38
- self.class_name = p['value']['className']
36
+ name = p["name"]
37
+ if name == "__proto__":
38
+ self.class_name = p["value"]["className"]
39
39
  continue
40
40
  # test if a getter/setter first
41
- value = p.get('get', p.get('set', p.get('value')))
41
+ value = p.get("get", p.get("set", p.get("value")))
42
42
  if value is None:
43
43
  continue
44
- preview = value.get('preview')
44
+ preview = value.get("preview")
45
45
  if preview is not None:
46
- value = JSObjectPreview(preview['properties'])
47
- elif value.get('className') == 'Function':
48
- value = value['description']
46
+ value = JSObjectPreview(preview["properties"])
47
+ elif value.get("className") == "Function":
48
+ value = value["description"]
49
49
  else:
50
- value = value.get('value')
50
+ value = value.get("value")
51
51
  self.data[name] = value
52
52
 
53
53
 
54
54
  class InspectorSession:
55
-
56
55
  def __init__(self, protocol: SessionProtocol, target_id: Optional[str] = None):
57
56
  """
58
57
  :param pymobiledevice3.services.web_protocol.session_protocol.SessionProtocol protocol: Session protocol.
@@ -64,14 +63,14 @@ class InspectorSession:
64
63
  self._dispatch_message_responses = {}
65
64
 
66
65
  self.response_methods = {
67
- 'Target.targetCreated': self._target_created,
68
- 'Target.targetDestroyed': self._target_destroyed,
69
- 'Target.dispatchMessageFromTarget': self._target_dispatch_message_from_target,
70
- 'Target.didCommitProvisionalTarget': self._target_did_commit_provisional_target,
71
- 'Console.messageAdded': self._console_message_added,
72
- 'Console.messagesCleared': lambda _: _,
73
- 'Console.messageRepeatCountUpdated': self._console_message_repeated_count_updated,
74
- 'Heap.garbageCollected': self._heap_garbage_collected,
66
+ "Target.targetCreated": self._target_created,
67
+ "Target.targetDestroyed": self._target_destroyed,
68
+ "Target.dispatchMessageFromTarget": self._target_dispatch_message_from_target,
69
+ "Target.didCommitProvisionalTarget": self._target_did_commit_provisional_target,
70
+ "Console.messageAdded": self._console_message_added,
71
+ "Console.messagesCleared": lambda _: _,
72
+ "Console.messageRepeatCountUpdated": self._console_message_repeated_count_updated,
73
+ "Heap.garbageCollected": self._heap_garbage_collected,
75
74
  }
76
75
 
77
76
  self._receive_task = asyncio.create_task(self._receive_loop())
@@ -88,64 +87,65 @@ class InspectorSession:
88
87
  while not protocol.inspector.wir_events:
89
88
  await asyncio.sleep(0)
90
89
  created = protocol.inspector.wir_events.pop(0)
91
- while 'targetInfo' not in created['params']:
90
+ while "targetInfo" not in created["params"]:
92
91
  created = protocol.inspector.wir_events.pop(0)
93
- target_id = created['params']['targetInfo']['targetId']
94
- logger.info(f'Created: {target_id}')
92
+ target_id = created["params"]["targetInfo"]["targetId"]
93
+ logger.info(f"Created: {target_id}")
95
94
  target = cls(protocol, target_id)
96
95
  return target
97
96
 
98
97
  def set_target_id(self, target_id):
99
98
  self.target_id = target_id
100
- logger.info(f'Changed to: {target_id}')
99
+ logger.info(f"Changed to: {target_id}")
101
100
 
102
101
  async def heap_gc(self):
103
- return await self.send_command('Heap.gc')
102
+ return await self.send_command("Heap.gc")
104
103
 
105
104
  async def heap_snapshot(self):
106
- snapshot = await self.send_command('Heap.snapshot')
105
+ snapshot = await self.send_command("Heap.snapshot")
107
106
  if self.target_id is not None:
108
- snapshot = json.loads(snapshot['params']['message'])
109
- snapshot = json.loads(snapshot)['result']['snapshotData']
107
+ snapshot = json.loads(snapshot["params"]["message"])
108
+ snapshot = json.loads(snapshot)["result"]["snapshotData"]
110
109
  return snapshot
111
110
 
112
111
  async def heap_enable(self):
113
- return await self.send_command('Heap.enable')
112
+ return await self.send_command("Heap.enable")
114
113
 
115
114
  async def console_enable(self):
116
- return await self.send_command('Console.enable')
115
+ return await self.send_command("Console.enable")
117
116
 
118
117
  async def runtime_enable(self):
119
- return await self.send_command('Runtime.enable')
118
+ return await self.send_command("Runtime.enable")
120
119
 
121
120
  async def send_command(self, method: str, **kwargs):
122
121
  if self.target_id is None:
123
122
  return await self.protocol.send_receive(method, **kwargs)
124
123
  else:
125
- return await self.send_and_receive({'method': method, 'params': kwargs})
124
+ return await self.send_and_receive({"method": method, "params": kwargs})
126
125
 
127
126
  async def runtime_evaluate(self, exp: str, return_by_value: bool = False):
128
127
  # if the expression is dict, it's needed to be in ()
129
128
  exp = exp.strip()
130
- if exp:
131
- if exp[0] == '{' and exp[-1] == '}':
132
- exp = f'({exp})'
133
-
134
- response = await self.send_and_receive({'method': 'Runtime.evaluate',
135
- 'params': {
136
- 'expression': exp,
137
- 'objectGroup': 'console',
138
- 'includeCommandLineAPI': True,
139
- 'doNotPauseOnExceptionsAndMuteConsole': False,
140
- 'silent': False,
141
- 'returnByValue': return_by_value,
142
- 'generatePreview': True,
143
- 'userGesture': True,
144
- 'awaitPromise': False,
145
- 'replMode': True,
146
- 'allowUnsafeEvalBlockedByCSP': False,
147
- 'uniqueContextId': '0.1'}
148
- })
129
+ if exp and exp[0] == "{" and exp[-1] == "}":
130
+ exp = f"({exp})"
131
+
132
+ response = await self.send_and_receive({
133
+ "method": "Runtime.evaluate",
134
+ "params": {
135
+ "expression": exp,
136
+ "objectGroup": "console",
137
+ "includeCommandLineAPI": True,
138
+ "doNotPauseOnExceptionsAndMuteConsole": False,
139
+ "silent": False,
140
+ "returnByValue": return_by_value,
141
+ "generatePreview": True,
142
+ "userGesture": True,
143
+ "awaitPromise": False,
144
+ "replMode": True,
145
+ "allowUnsafeEvalBlockedByCSP": False,
146
+ "uniqueContextId": "0.1",
147
+ },
148
+ })
149
149
 
150
150
  return await self._parse_runtime_evaluate(response)
151
151
 
@@ -154,18 +154,19 @@ class InspectorSession:
154
154
 
155
155
  async def send_and_receive(self, message: dict) -> dict:
156
156
  if self.target_id is None:
157
- message_id = await self.protocol.send_command(message['method'], **message.get('params', {}))
157
+ message_id = await self.protocol.send_command(message["method"], **message.get("params", {}))
158
158
  return await self.protocol.wait_for_message(message_id)
159
159
  else:
160
160
  message_id = await self.send_message_to_target(message)
161
161
  return await self.receive_response_by_id(message_id)
162
162
 
163
163
  async def send_message_to_target(self, message: dict) -> int:
164
- message['id'] = self.message_id
164
+ message["id"] = self.message_id
165
165
  self.message_id += 1
166
- await self.protocol.send_command('Target.sendMessageToTarget', targetId=self.target_id,
167
- message=json.dumps(message))
168
- return message['id']
166
+ await self.protocol.send_command(
167
+ "Target.sendMessageToTarget", targetId=self.target_id, message=json.dumps(message)
168
+ )
169
+ return message["id"]
169
170
 
170
171
  async def _receive_loop(self):
171
172
  while True:
@@ -173,11 +174,11 @@ class InspectorSession:
173
174
  await asyncio.sleep(0)
174
175
 
175
176
  response = self.protocol.inspector.wir_events.pop(0)
176
- response_method = response['method']
177
+ response_method = response["method"]
177
178
  if response_method in self.response_methods:
178
179
  self.response_methods[response_method](response)
179
180
  else:
180
- logger.error(f'Unknown response: {response}')
181
+ logger.error(f"Unknown response: {response}")
181
182
 
182
183
  async def receive_response_by_id(self, message_id: int) -> dict:
183
184
  while True:
@@ -187,64 +188,67 @@ class InspectorSession:
187
188
 
188
189
  async def get_properties(self, object_id: str) -> JSObjectProperties:
189
190
  message = await self.send_command(
190
- 'Runtime.getProperties', objectId=object_id, ownProperties=True, generatePreview=True)
191
+ "Runtime.getProperties", objectId=object_id, ownProperties=True, generatePreview=True
192
+ )
191
193
  if self.target_id is not None:
192
- message = json.loads(message['params']['message'])['result']
193
- return JSObjectProperties(message['properties'])
194
+ message = json.loads(message["params"]["message"])["result"]
195
+ return JSObjectProperties(message["properties"])
194
196
 
195
197
  async def _parse_runtime_evaluate(self, response: dict):
196
- if self.target_id is None:
197
- message = response
198
- else:
199
- message = json.loads(response['params']['message'])
200
- result = message['result']['result']
201
- if result.get('subtype', '') == 'error':
202
- properties = await self.get_properties(result['objectId'])
203
- raise InspectorEvaluateError(properties.class_name, properties['message'], properties.get('line'),
204
- properties.get('column'), properties.get('stack', '').split('\n'))
205
- elif result['type'] == 'bigint':
206
- return result['description']
207
- elif result['type'] == 'undefined':
198
+ message = response if self.target_id is None else json.loads(response["params"]["message"])
199
+ result = message["result"]["result"]
200
+ if result.get("subtype", "") == "error":
201
+ properties = await self.get_properties(result["objectId"])
202
+ raise InspectorEvaluateError(
203
+ properties.class_name,
204
+ properties["message"],
205
+ properties.get("line"),
206
+ properties.get("column"),
207
+ properties.get("stack", "").split("\n"),
208
+ )
209
+ elif result["type"] == "bigint":
210
+ return result["description"]
211
+ elif result["type"] == "undefined":
208
212
  pass
209
- elif result['type'] == 'object':
210
- value = result.get('value')
213
+ elif result["type"] == "object":
214
+ value = result.get("value")
211
215
  if value is not None:
212
216
  return value
213
217
 
214
218
  # TODO: JSObjectProperties()
215
- preview = result['preview']
216
- preview_buf = '{\n'
217
- for p in result['preview']['properties']:
218
- value = p.get('value', 'NOT_SUPPORTED_FOR_PREVIEW')
219
- preview_buf += f'\t{p["name"]}: {value}, // {p["type"]}\n'
220
- if preview.get('overflow'):
221
- preview_buf += '\t// ...\n'
222
- preview_buf += '}'
223
- return f'[object {result["className"]}]\n{preview_buf}'
224
- elif result['type'] == 'function':
225
- return result['description']
219
+ preview = result["preview"]
220
+ preview_buf = "{\n"
221
+ for p in result["preview"]["properties"]:
222
+ value = p.get("value", "NOT_SUPPORTED_FOR_PREVIEW")
223
+ preview_buf += f"\t{p['name']}: {value}, // {p['type']}\n"
224
+ if preview.get("overflow"):
225
+ preview_buf += "\t// ...\n"
226
+ preview_buf += "}"
227
+ return f"[object {result['className']}]\n{preview_buf}"
228
+ elif result["type"] == "function":
229
+ return result["description"]
226
230
  else:
227
- return result['value']
231
+ return result["value"]
228
232
 
229
233
  # response methods
230
234
  def _target_dispatch_message_from_target(self, response: dict):
231
- target_message = json.loads(response['params']['message'])
232
- receive_message_id = target_message.get('id')
235
+ target_message = json.loads(response["params"]["message"])
236
+ receive_message_id = target_message.get("id")
233
237
  if receive_message_id is None:
234
238
  self._missing_id_in_message(target_message)
235
239
  return
236
240
  self._dispatch_message_responses[receive_message_id] = response
237
241
 
238
242
  def _missing_id_in_message(self, message: dict):
239
- handler = self.response_methods.get(message['method'])
243
+ handler = self.response_methods.get(message["method"])
240
244
  if handler is not None:
241
245
  handler(message)
242
246
  else:
243
- logger.critical(f'unhandled message: {message}')
247
+ logger.critical(f"unhandled message: {message}")
244
248
 
245
249
  def _console_message_added(self, message: dict):
246
- log_level = message['params']['message']['level']
247
- text = message['params']['message']['text']
250
+ log_level = message["params"]["message"]["level"]
251
+ text = message["params"]["message"]["text"]
248
252
  self._last_console_message = message
249
253
  webinspector_logger_handlers[log_level](text)
250
254
 
@@ -252,7 +256,7 @@ class InspectorSession:
252
256
  self._console_message_added(self._last_console_message)
253
257
 
254
258
  def _heap_garbage_collected(self, message: dict):
255
- heap_logger.debug(message['params'])
259
+ heap_logger.debug(message["params"])
256
260
 
257
261
  def _target_created(self, response: dict):
258
262
  pass
@@ -261,4 +265,4 @@ class InspectorSession:
261
265
  pass
262
266
 
263
267
  def _target_did_commit_provisional_target(self, response: dict):
264
- self.set_target_id(response['params']['newTargetId'])
268
+ self.set_target_id(response["params"]["newTargetId"])
@@ -69,14 +69,14 @@ class SeleniumApi(ABC):
69
69
  def screenshot(self, filename):
70
70
  png = self.screenshot_as_png()
71
71
  try:
72
- with open(filename, 'wb') as f:
72
+ with open(filename, "wb") as f:
73
73
  f.write(png)
74
74
  except IOError:
75
75
  return False
76
76
  return True
77
77
 
78
78
  def screenshot_as_png(self):
79
- return b64decode(self.screenshot_as_base64.encode('ascii'))
79
+ return b64decode(self.screenshot_as_base64.encode("ascii"))
80
80
 
81
81
  def get_screenshot_as_base64(self):
82
82
  return self.screenshot_as_base64
@@ -5,7 +5,7 @@ from pymobiledevice3.exceptions import WirError
5
5
 
6
6
 
7
7
  class SessionProtocol:
8
- def __init__(self, inspector, id_, app, page, method_prefix='Automation'):
8
+ def __init__(self, inspector, id_, app, page, method_prefix="Automation"):
9
9
  """
10
10
  :param pymobiledevice3.services.webinspector.WebinspectorService inspector:
11
11
  """
@@ -19,19 +19,24 @@ class SessionProtocol:
19
19
  async def send_command(self, method, **kwargs):
20
20
  wir_id = self._wir_messages_id
21
21
  self._wir_messages_id += 1
22
- await self.inspector.send_socket_data(self.id_, self.app.id_, self.page.id_, {
23
- 'method': f'{self.method_prefix}.{method}' if self.method_prefix else method,
24
- 'params': kwargs,
25
- 'id': wir_id,
26
- })
22
+ await self.inspector.send_socket_data(
23
+ self.id_,
24
+ self.app.id_,
25
+ self.page.id_,
26
+ {
27
+ "method": f"{self.method_prefix}.{method}" if self.method_prefix else method,
28
+ "params": kwargs,
29
+ "id": wir_id,
30
+ },
31
+ )
27
32
  return wir_id
28
33
 
29
34
  async def get_response(self, wir_id):
30
35
  response = await self.wait_for_message(wir_id)
31
- if 'result' in response:
32
- return response['result']
33
- elif 'error' in response:
34
- raise WirError(response['error']['message'])
36
+ if "result" in response:
37
+ return response["result"]
38
+ elif "error" in response:
39
+ raise WirError(response["error"]["message"])
35
40
 
36
41
  async def send_receive(self, method, wait_for_response=True, **kwargs):
37
42
  wir_id = await self.send_command(method, **kwargs)
@@ -12,19 +12,19 @@ class SwitchTo:
12
12
 
13
13
  @property
14
14
  def active_element(self) -> WebElement:
15
- """ Returns the element with focus, or BODY if nothing has focus. """
15
+ """Returns the element with focus, or BODY if nothing has focus."""
16
16
  self.session.wait_for_navigation_to_complete()
17
- elem = self.session.evaluate_js_function('function() { return document.activeElement; }', include_frame=False)
17
+ elem = self.session.evaluate_js_function("function() { return document.activeElement; }", include_frame=False)
18
18
  return WebElement(self.session, elem)
19
19
 
20
20
  @property
21
21
  def alert(self) -> Alert:
22
- """ Switches focus to an alert on the page. """
22
+ """Switches focus to an alert on the page."""
23
23
  return Alert(self.session)
24
24
 
25
25
  def default_content(self):
26
- """ Switch focus to the default frame. """
27
- self.session.switch_to_browsing_context('')
26
+ """Switch focus to the default frame."""
27
+ self.session.switch_to_browsing_context("")
28
28
 
29
29
  def frame(self, frame_reference):
30
30
  """
@@ -32,7 +32,7 @@ class SwitchTo:
32
32
  :param frame_reference: The name of the window to switch to, an integer representing the index,
33
33
  or a web element that is an (i)frame to switch to.
34
34
  """
35
- if isinstance(frame_reference, int) or isinstance(frame_reference, WebElement):
35
+ if isinstance(frame_reference, (int, WebElement)):
36
36
  frame = frame_reference
37
37
  elif isinstance(frame_reference, str):
38
38
  elem = self.session.find_elements(By.ID, frame_reference)
@@ -40,7 +40,7 @@ class SwitchTo:
40
40
  elem = self.session.find_elements(By.NAME, frame_reference)
41
41
  frame = WebElement(self.session, elem)
42
42
  else:
43
- raise ValueError()
43
+ raise TypeError()
44
44
 
45
45
  self.session.wait_for_navigation_to_complete()
46
46
  if isinstance(frame, int):
@@ -48,8 +48,8 @@ class SwitchTo:
48
48
  else:
49
49
  self.session.switch_to_frame(frame_handle=frame)
50
50
 
51
- def new_window(self, type_=''):
52
- """ Switches to a new top-level browsing context. """
51
+ def new_window(self, type_=""):
52
+ """Switches to a new top-level browsing context."""
53
53
  self.session.switch_to_window(self.session.create_window(type_))
54
54
 
55
55
  def parent_frame(self):
@@ -58,10 +58,9 @@ class SwitchTo:
58
58
  level browsing context, the context remains unchanged.
59
59
  """
60
60
  self.session.wait_for_navigation_to_complete()
61
- self.session.switch_to_browsing_context_frame(self.session.top_level_handle,
62
- self.session.current_parent_handle)
61
+ self.session.switch_to_browsing_context_frame(self.session.top_level_handle, self.session.current_parent_handle)
63
62
  self.session.switch_to_browsing_context(self.session.current_parent_handle)
64
63
 
65
64
  def window(self, window_name):
66
- """ Switches focus to the specified window. """
65
+ """Switches focus to the specified window."""
67
66
  self.session.switch_to_window(window_name)