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
pymobiledevice3/usbmux.py CHANGED
@@ -5,76 +5,115 @@ import time
5
5
  from dataclasses import dataclass
6
6
  from typing import Optional
7
7
 
8
- from construct import Const, CString, Enum, FixedSized, GreedyBytes, Int16ul, Int32ul, Padding, Prefixed, StreamError, \
9
- Struct, Switch, this
8
+ from construct import (
9
+ Const,
10
+ CString,
11
+ Enum,
12
+ FixedSized,
13
+ GreedyBytes,
14
+ Int16ul,
15
+ Int32ul,
16
+ Padding,
17
+ Prefixed,
18
+ StreamError,
19
+ Struct,
20
+ Switch,
21
+ this,
22
+ )
10
23
 
11
- from pymobiledevice3.exceptions import BadCommandError, BadDevError, ConnectionFailedError, \
12
- ConnectionFailedToUsbmuxdError, MuxException, MuxVersionError, NotPairedError
24
+ from pymobiledevice3.exceptions import (
25
+ BadCommandError,
26
+ BadDevError,
27
+ ConnectionFailedError,
28
+ ConnectionFailedToUsbmuxdError,
29
+ MuxException,
30
+ MuxVersionError,
31
+ NotPairedError,
32
+ )
13
33
  from pymobiledevice3.osu.os_utils import get_os_utils
14
34
 
15
- usbmuxd_version = Enum(Int32ul,
16
- BINARY=0,
17
- PLIST=1,
18
- )
19
-
20
- usbmuxd_result = Enum(Int32ul,
21
- OK=0,
22
- BADCOMMAND=1,
23
- BADDEV=2,
24
- CONNREFUSED=3,
25
- NOSUCHSERVICE=4,
26
- BADVERSION=6,
27
- )
28
-
29
- usbmuxd_msgtype = Enum(Int32ul,
30
- RESULT=1,
31
- CONNECT=2,
32
- LISTEN=3,
33
- ADD=4,
34
- REMOVE=5,
35
- PAIRED=6,
36
- PLIST=8,
37
- )
35
+ usbmuxd_version = Enum(
36
+ Int32ul,
37
+ BINARY=0,
38
+ PLIST=1,
39
+ )
40
+
41
+ usbmuxd_result = Enum(
42
+ Int32ul,
43
+ OK=0,
44
+ BADCOMMAND=1,
45
+ BADDEV=2,
46
+ CONNREFUSED=3,
47
+ NOSUCHSERVICE=4,
48
+ BADVERSION=6,
49
+ )
50
+
51
+ usbmuxd_msgtype = Enum(
52
+ Int32ul,
53
+ RESULT=1,
54
+ CONNECT=2,
55
+ LISTEN=3,
56
+ ADD=4,
57
+ REMOVE=5,
58
+ PAIRED=6,
59
+ PLIST=8,
60
+ )
38
61
 
39
62
  usbmuxd_header = Struct(
40
- 'version' / usbmuxd_version, # protocol version
41
- 'message' / usbmuxd_msgtype, # message type
42
- 'tag' / Int32ul, # responses to this query will echo back this tag
63
+ "version" / usbmuxd_version, # protocol version
64
+ "message" / usbmuxd_msgtype, # message type
65
+ "tag" / Int32ul, # responses to this query will echo back this tag
43
66
  )
44
67
 
45
- usbmuxd_request = Prefixed(Int32ul, Struct(
46
- 'header' / usbmuxd_header,
47
- 'data' / Switch(this.header.message, {
48
- usbmuxd_msgtype.CONNECT: Struct(
49
- 'device_id' / Int32ul,
50
- 'port' / Int16ul, # TCP port number
51
- 'reserved' / Const(0, Int16ul),
68
+ usbmuxd_request = Prefixed(
69
+ Int32ul,
70
+ Struct(
71
+ "header" / usbmuxd_header,
72
+ "data"
73
+ / Switch(
74
+ this.header.message,
75
+ {
76
+ usbmuxd_msgtype.CONNECT: Struct(
77
+ "device_id" / Int32ul,
78
+ "port" / Int16ul, # TCP port number
79
+ "reserved" / Const(0, Int16ul),
80
+ ),
81
+ usbmuxd_msgtype.PLIST: GreedyBytes,
82
+ },
52
83
  ),
53
- usbmuxd_msgtype.PLIST: GreedyBytes,
54
- }),
55
- ), includelength=True)
84
+ ),
85
+ includelength=True,
86
+ )
56
87
 
57
88
  usbmuxd_device_record = Struct(
58
- 'device_id' / Int32ul,
59
- 'product_id' / Int16ul,
60
- 'serial_number' / FixedSized(256, CString('ascii')),
89
+ "device_id" / Int32ul,
90
+ "product_id" / Int16ul,
91
+ "serial_number" / FixedSized(256, CString("ascii")),
61
92
  Padding(2),
62
- 'location' / Int32ul
93
+ "location" / Int32ul,
63
94
  )
64
95
 
65
- usbmuxd_response = Prefixed(Int32ul, Struct(
66
- 'header' / usbmuxd_header,
67
- 'data' / Switch(this.header.message, {
68
- usbmuxd_msgtype.RESULT: Struct(
69
- 'result' / usbmuxd_result,
96
+ usbmuxd_response = Prefixed(
97
+ Int32ul,
98
+ Struct(
99
+ "header" / usbmuxd_header,
100
+ "data"
101
+ / Switch(
102
+ this.header.message,
103
+ {
104
+ usbmuxd_msgtype.RESULT: Struct(
105
+ "result" / usbmuxd_result,
106
+ ),
107
+ usbmuxd_msgtype.ADD: usbmuxd_device_record,
108
+ usbmuxd_msgtype.REMOVE: Struct(
109
+ "device_id" / Int32ul,
110
+ ),
111
+ usbmuxd_msgtype.PLIST: GreedyBytes,
112
+ },
70
113
  ),
71
- usbmuxd_msgtype.ADD: usbmuxd_device_record,
72
- usbmuxd_msgtype.REMOVE: Struct(
73
- 'device_id' / Int32ul,
74
- ),
75
- usbmuxd_msgtype.PLIST: GreedyBytes,
76
- }),
77
- ), includelength=True)
114
+ ),
115
+ includelength=True,
116
+ )
78
117
 
79
118
 
80
119
  @dataclass
@@ -87,24 +126,24 @@ class MuxDevice:
87
126
  mux = create_mux(usbmux_address=usbmux_address)
88
127
  try:
89
128
  return mux.connect(self, port)
90
- except: # noqa: E722
129
+ except:
91
130
  mux.close()
92
131
  raise
93
132
 
94
133
  @property
95
134
  def is_usb(self) -> bool:
96
- return self.connection_type == 'USB'
135
+ return self.connection_type == "USB"
97
136
 
98
137
  @property
99
138
  def is_network(self) -> bool:
100
- return self.connection_type == 'Network'
139
+ return self.connection_type == "Network"
101
140
 
102
141
  def matches_udid(self, udid: str) -> bool:
103
- return self.serial.replace('-', '') == udid.replace('-', '')
142
+ return self.serial.replace("-", "") == udid.replace("-", "")
104
143
 
105
144
 
106
145
  class SafeStreamSocket:
107
- """ wrapper to native python socket object to be used with construct as a stream """
146
+ """wrapper to native python socket object to be used with construct as a stream"""
108
147
 
109
148
  def __init__(self, address, family):
110
149
  self._offset = 0
@@ -117,12 +156,12 @@ class SafeStreamSocket:
117
156
  return len(msg)
118
157
 
119
158
  def recv(self, size: int) -> bytes:
120
- msg = b''
159
+ msg = b""
121
160
  while len(msg) < size:
122
161
  chunk = self.sock.recv(size - len(msg))
123
162
  self._offset += len(chunk)
124
163
  if not chunk:
125
- raise MuxException('socket connection broken')
164
+ raise MuxException("socket connection broken")
126
165
  msg += chunk
127
166
  return msg
128
167
 
@@ -144,18 +183,18 @@ class SafeStreamSocket:
144
183
 
145
184
  class MuxConnection:
146
185
  # used on Windows
147
- ITUNES_HOST = ('127.0.0.1', 27015)
186
+ ITUNES_HOST = ("127.0.0.1", 27015)
148
187
 
149
188
  # used for macOS and Linux
150
- USBMUXD_PIPE = '/var/run/usbmuxd'
189
+ USBMUXD_PIPE = "/var/run/usbmuxd"
151
190
 
152
191
  @staticmethod
153
192
  def create_usbmux_socket(usbmux_address: Optional[str] = None) -> SafeStreamSocket:
154
193
  try:
155
194
  if usbmux_address is not None:
156
- if ':' in usbmux_address:
195
+ if ":" in usbmux_address:
157
196
  # assume tcp address
158
- hostname, port = usbmux_address.split(':')
197
+ hostname, port = usbmux_address.split(":")
159
198
  port = int(port)
160
199
  address = (hostname, port)
161
200
  family = socket.AF_INET
@@ -166,8 +205,8 @@ class MuxConnection:
166
205
  else:
167
206
  address, family = get_os_utils().usbmux_address
168
207
  return SafeStreamSocket(address, family)
169
- except ConnectionRefusedError:
170
- raise ConnectionFailedToUsbmuxdError()
208
+ except ConnectionRefusedError as e:
209
+ raise ConnectionFailedToUsbmuxdError() from e
171
210
 
172
211
  @staticmethod
173
212
  def create(usbmux_address: Optional[str] = None):
@@ -176,8 +215,8 @@ class MuxConnection:
176
215
 
177
216
  try:
178
217
  message = usbmuxd_request.build({
179
- 'header': {'version': usbmuxd_version.PLIST, 'message': usbmuxd_msgtype.PLIST, 'tag': 1},
180
- 'data': plistlib.dumps({'MessageType': 'ReadBUID'})
218
+ "header": {"version": usbmuxd_version.PLIST, "message": usbmuxd_msgtype.PLIST, "tag": 1},
219
+ "data": plistlib.dumps({"MessageType": "ReadBUID"}),
181
220
  })
182
221
  sock.send(message)
183
222
  response = usbmuxd_response.parse_stream(sock)
@@ -192,7 +231,7 @@ class MuxConnection:
192
231
  elif response.header.version == usbmuxd_version.PLIST:
193
232
  return PlistMuxConnection(sock)
194
233
 
195
- raise MuxVersionError(f'usbmuxd returned unsupported version: {response.version}')
234
+ raise MuxVersionError(f"usbmuxd returned unsupported version: {response.version}")
196
235
 
197
236
  def __init__(self, sock: SafeStreamSocket):
198
237
  self._sock = sock
@@ -209,30 +248,30 @@ class MuxConnection:
209
248
 
210
249
  @abc.abstractmethod
211
250
  def _connect(self, device_id: int, port: int):
212
- """ initiate a "Connect" request to target port """
251
+ """initiate a "Connect" request to target port"""
213
252
  pass
214
253
 
215
254
  @abc.abstractmethod
216
- def get_device_list(self, timeout: float = None):
255
+ def get_device_list(self, timeout: Optional[float] = None):
217
256
  """
218
257
  request an update to current device list
219
258
  """
220
259
  pass
221
260
 
222
261
  def connect(self, device: MuxDevice, port: int) -> socket.socket:
223
- """ connect to a relay port on target machine and get a raw python socket object for the connection """
262
+ """connect to a relay port on target machine and get a raw python socket object for the connection"""
224
263
  self._connect(device.devid, socket.htons(port))
225
264
  self._connected = True
226
265
  return self._sock.sock
227
266
 
228
267
  def close(self):
229
- """ close current socket """
268
+ """close current socket"""
230
269
  self._sock.close()
231
270
 
232
271
  def _assert_not_connected(self):
233
- """ verify active state is in state for control messages """
272
+ """verify active state is in state for control messages"""
234
273
  if self._connected:
235
- raise MuxException('Mux is connected, cannot issue control packets')
274
+ raise MuxException("Mux is connected, cannot issue control packets")
236
275
 
237
276
  def _raise_mux_exception(self, result: int, message: Optional[str] = None) -> None:
238
277
  exceptions = {
@@ -253,14 +292,14 @@ class MuxConnection:
253
292
 
254
293
 
255
294
  class BinaryMuxConnection(MuxConnection):
256
- """ old binary protocol """
295
+ """old binary protocol"""
257
296
 
258
297
  def __init__(self, sock: SafeStreamSocket):
259
298
  super().__init__(sock)
260
299
  self._version = usbmuxd_version.BINARY
261
300
 
262
- def get_device_list(self, timeout: float = None):
263
- """ use timeout to wait for the device list to be fully populated """
301
+ def get_device_list(self, timeout: Optional[float] = None):
302
+ """use timeout to wait for the device list to be fully populated"""
264
303
  self._assert_not_connected()
265
304
  end = time.time() + timeout
266
305
  self.listen()
@@ -270,55 +309,54 @@ class BinaryMuxConnection(MuxConnection):
270
309
  self._receive_device_state_update()
271
310
  except (BlockingIOError, StreamError):
272
311
  continue
273
- except IOError:
312
+ except IOError as e:
274
313
  try:
275
314
  self._sock.setblocking(True)
276
315
  self.close()
277
316
  except OSError:
278
317
  pass
279
- raise MuxException('Exception in listener socket')
318
+ raise MuxException("Exception in listener socket") from e
280
319
 
281
320
  def listen(self):
282
- """ start listening for events of attached and detached devices """
321
+ """start listening for events of attached and detached devices"""
283
322
  self._send_receive(usbmuxd_msgtype.LISTEN)
284
323
 
285
324
  def _connect(self, device_id: int, port: int):
286
- self._send({'header': {'version': self._version,
287
- 'message': usbmuxd_msgtype.CONNECT,
288
- 'tag': self._tag},
289
- 'data': {'device_id': device_id, 'port': port},
290
- })
325
+ self._send({
326
+ "header": {"version": self._version, "message": usbmuxd_msgtype.CONNECT, "tag": self._tag},
327
+ "data": {"device_id": device_id, "port": port},
328
+ })
291
329
  response = self._receive()
292
330
  if response.header.message != usbmuxd_msgtype.RESULT:
293
- raise MuxException(f'unexpected message type received: {response}')
331
+ raise MuxException(f"unexpected message type received: {response}")
294
332
 
295
333
  if response.data.result != usbmuxd_result.OK:
296
- raise self._raise_mux_exception(int(response.data.result),
297
- f'failed to connect to device: {device_id} at port: {port}. reason: '
298
- f'{response.data.result}')
334
+ raise self._raise_mux_exception(
335
+ int(response.data.result),
336
+ f"failed to connect to device: {device_id} at port: {port}. reason: {response.data.result}",
337
+ )
299
338
 
300
339
  def _send(self, data: dict) -> None:
301
340
  self._assert_not_connected()
302
341
  self._sock.send(usbmuxd_request.build(data))
303
342
  self._tag += 1
304
343
 
305
- def _receive(self, expected_tag: int = None):
344
+ def _receive(self, expected_tag: Optional[int] = None):
306
345
  self._assert_not_connected()
307
346
  response = usbmuxd_response.parse_stream(self._sock)
308
347
  if expected_tag and response.header.tag != expected_tag:
309
- raise MuxException(f'Reply tag mismatch: expected {expected_tag}, got {response.header.tag}')
348
+ raise MuxException(f"Reply tag mismatch: expected {expected_tag}, got {response.header.tag}")
310
349
  return response
311
350
 
312
351
  def _send_receive(self, message_type: int):
313
- self._send({'header': {'version': self._version, 'message': message_type, 'tag': self._tag},
314
- 'data': b''})
352
+ self._send({"header": {"version": self._version, "message": message_type, "tag": self._tag}, "data": b""})
315
353
  response = self._receive(self._tag - 1)
316
354
  if response.header.message != usbmuxd_msgtype.RESULT:
317
- raise MuxException(f'unexpected message type received: {response}')
355
+ raise MuxException(f"unexpected message type received: {response}")
318
356
 
319
357
  result = response.data.result
320
358
  if result != usbmuxd_result.OK:
321
- raise self._raise_mux_exception(int(result), f'{message_type} failed: error {result}')
359
+ raise self._raise_mux_exception(int(result), f"{message_type} failed: error {result}")
322
360
 
323
361
  def _add_device(self, device: MuxDevice):
324
362
  self.devices.append(device)
@@ -330,11 +368,11 @@ class BinaryMuxConnection(MuxConnection):
330
368
  response = self._receive()
331
369
  if response.header.message == usbmuxd_msgtype.ADD:
332
370
  # old protocol only supported USB devices
333
- self._add_device(MuxDevice(response.data.device_id, response.data.serial_number, 'USB'))
371
+ self._add_device(MuxDevice(response.data.device_id, response.data.serial_number, "USB"))
334
372
  elif response.header.message == usbmuxd_msgtype.REMOVE:
335
373
  self._remove_device(response.data.device_id)
336
374
  else:
337
- raise MuxException(f'Invalid packet type received: {response}')
375
+ raise MuxException(f"Invalid packet type received: {response}")
338
376
 
339
377
 
340
378
  class PlistMuxConnection(BinaryMuxConnection):
@@ -343,71 +381,77 @@ class PlistMuxConnection(BinaryMuxConnection):
343
381
  self._version = usbmuxd_version.PLIST
344
382
 
345
383
  def listen(self) -> None:
346
- self._send_receive({'MessageType': 'Listen'})
384
+ self._send_receive({"MessageType": "Listen"})
347
385
 
348
386
  def get_pair_record(self, serial: str) -> dict:
349
387
  # serials are saved inside usbmuxd without '-'
350
- self._send({'MessageType': 'ReadPairRecord', 'PairRecordID': serial})
388
+ self._send({"MessageType": "ReadPairRecord", "PairRecordID": serial})
351
389
  response = self._receive(self._tag - 1)
352
- pair_record = response.get('PairRecordData')
390
+ pair_record = response.get("PairRecordData")
353
391
  if pair_record is None:
354
- raise NotPairedError('device should be paired first')
392
+ raise NotPairedError("device should be paired first")
355
393
  return plistlib.loads(pair_record)
356
394
 
357
- def get_device_list(self, timeout: float = None) -> None:
358
- """ get device list synchronously without waiting the timeout """
395
+ def get_device_list(self, timeout: Optional[float] = None) -> None:
396
+ """get device list synchronously without waiting the timeout"""
359
397
  self.devices = []
360
- self._send({'MessageType': 'ListDevices'})
398
+ self._send({"MessageType": "ListDevices"})
361
399
  response = self._receive(self._tag - 1)
362
- device_list = response.get('DeviceList')
400
+ device_list = response.get("DeviceList")
363
401
  if device_list is None:
364
- raise MuxException(f'Got an invalid response from usbmux: {response}')
402
+ raise MuxException(f"Got an invalid response from usbmux: {response}")
365
403
  for response in device_list:
366
- if response['MessageType'] == 'Attached':
367
- super()._add_device(MuxDevice(response['DeviceID'], response['Properties']['SerialNumber'],
368
- response['Properties']['ConnectionType']))
369
- elif response['MessageType'] == 'Detached':
370
- super()._remove_device(response['DeviceID'])
404
+ if response["MessageType"] == "Attached":
405
+ super()._add_device(
406
+ MuxDevice(
407
+ response["DeviceID"],
408
+ response["Properties"]["SerialNumber"],
409
+ response["Properties"]["ConnectionType"],
410
+ )
411
+ )
412
+ elif response["MessageType"] == "Detached":
413
+ super()._remove_device(response["DeviceID"])
371
414
  else:
372
- raise MuxException(f'Invalid packet type received: {response}')
415
+ raise MuxException(f"Invalid packet type received: {response}")
373
416
 
374
417
  def get_buid(self) -> str:
375
- """ get SystemBUID """
376
- self._send({'MessageType': 'ReadBUID'})
377
- return self._receive(self._tag - 1)['BUID']
418
+ """get SystemBUID"""
419
+ self._send({"MessageType": "ReadBUID"})
420
+ return self._receive(self._tag - 1)["BUID"]
378
421
 
379
422
  def save_pair_record(self, serial: str, device_id: int, record_data: bytes):
380
423
  # serials are saved inside usbmuxd without '-'
381
- self._send_receive({'MessageType': 'SavePairRecord',
382
- 'PairRecordID': serial,
383
- 'PairRecordData': record_data,
384
- 'DeviceID': device_id})
424
+ self._send_receive({
425
+ "MessageType": "SavePairRecord",
426
+ "PairRecordID": serial,
427
+ "PairRecordData": record_data,
428
+ "DeviceID": device_id,
429
+ })
385
430
 
386
431
  def _connect(self, device_id: int, port: int):
387
- self._send_receive({'MessageType': 'Connect', 'DeviceID': device_id, 'PortNumber': port})
432
+ self._send_receive({"MessageType": "Connect", "DeviceID": device_id, "PortNumber": port})
388
433
 
389
434
  def _send(self, data: dict):
390
- request = {'ClientVersionString': 'qt4i-usbmuxd', 'ProgName': 'pymobiledevice3', 'kLibUSBMuxVersion': 3}
435
+ request = {"ClientVersionString": "qt4i-usbmuxd", "ProgName": "pymobiledevice3", "kLibUSBMuxVersion": 3}
391
436
  request.update(data)
392
- super()._send({'header': {'version': self._version,
393
- 'message': usbmuxd_msgtype.PLIST,
394
- 'tag': self._tag},
395
- 'data': plistlib.dumps(request),
396
- })
437
+ super()._send({
438
+ "header": {"version": self._version, "message": usbmuxd_msgtype.PLIST, "tag": self._tag},
439
+ "data": plistlib.dumps(request),
440
+ })
397
441
 
398
- def _receive(self, expected_tag: int = None) -> dict:
442
+ def _receive(self, expected_tag: Optional[int] = None) -> dict:
399
443
  response = super()._receive(expected_tag=expected_tag)
400
444
  if response.header.message != usbmuxd_msgtype.PLIST:
401
- raise MuxException(f'Received non-plist type {response}')
445
+ raise MuxException(f"Received non-plist type {response}")
402
446
  return plistlib.loads(response.data)
403
447
 
404
448
  def _send_receive(self, data: dict):
405
449
  self._send(data)
406
450
  response = self._receive(self._tag - 1)
407
- if response['MessageType'] != 'Result':
408
- raise MuxException(f'got an invalid message: {response}')
409
- if response['Number'] != 0:
410
- raise self._raise_mux_exception(response['Number'], f'got an error message: {response}')
451
+ if response["MessageType"] != "Result":
452
+ raise MuxException(f"got an invalid message: {response}")
453
+ if response["Number"] != 0:
454
+ raise self._raise_mux_exception(response["Number"], f"got an error message: {response}")
411
455
 
412
456
 
413
457
  def create_mux(usbmux_address: Optional[str] = None) -> MuxConnection:
@@ -424,8 +468,9 @@ def list_devices(usbmux_address: Optional[str] = None) -> list[MuxDevice]:
424
468
  return devices
425
469
 
426
470
 
427
- def select_device(udid: str = None, connection_type: str = None, usbmux_address: Optional[str] = None) \
428
- -> Optional[MuxDevice]:
471
+ def select_device(
472
+ udid: Optional[str] = None, connection_type: Optional[str] = None, usbmux_address: Optional[str] = None
473
+ ) -> Optional[MuxDevice]:
429
474
  """
430
475
  select a UsbMux device according to given arguments.
431
476
  if more than one device could be selected, always prefer the usb one.
pymobiledevice3/utils.py CHANGED
@@ -15,16 +15,16 @@ def plist_access_path(d, path: tuple, type_=None, required=False):
15
15
  if d is None:
16
16
  break
17
17
 
18
- if type_ == bool and isinstance(d, str):
19
- if d.lower() not in ('true', 'false'):
18
+ if type_ is bool and isinstance(d, str):
19
+ if d.lower() not in ("true", "false"):
20
20
  raise ValueError()
21
- d = 'true' == d.lower()
21
+ d = d.lower() == "true"
22
22
  elif type_ is not None and not isinstance(d, type_):
23
23
  # wrong type
24
24
  d = None
25
25
 
26
26
  if d is None and required:
27
- raise KeyError(f'path: {path} doesn\'t exist in given plist object')
27
+ raise KeyError(f"path: {path} doesn't exist in given plist object")
28
28
 
29
29
  return d
30
30
 
@@ -35,7 +35,7 @@ def bytes_to_uint(b: bytes):
35
35
 
36
36
  def try_decode(s: bytes):
37
37
  try:
38
- return s.decode('utf8')
38
+ return s.decode("utf8")
39
39
  except UnicodeDecodeError:
40
40
  return s
41
41
 
@@ -45,7 +45,7 @@ def asyncio_print_traceback(f: Callable):
45
45
  async def wrapper(*args, **kwargs):
46
46
  try:
47
47
  return await f(*args, **kwargs)
48
- except (Exception, RuntimeError) as e: # noqa: E72
48
+ except (Exception, RuntimeError) as e:
49
49
  if not isinstance(e, asyncio.CancelledError):
50
50
  traceback.print_exc()
51
51
  raise
@@ -57,7 +57,7 @@ def get_asyncio_loop() -> asyncio.AbstractEventLoop:
57
57
  try:
58
58
  loop = asyncio.get_running_loop()
59
59
  if loop.is_closed():
60
- raise RuntimeError('The existing loop is closed.')
60
+ raise RuntimeError("The existing loop is closed.")
61
61
  except RuntimeError:
62
62
  # This happens when there is no current event loop
63
63
  loop = asyncio.new_event_loop()
@@ -67,14 +67,17 @@ def get_asyncio_loop() -> asyncio.AbstractEventLoop:
67
67
 
68
68
  def file_download(url: str, outfile: Path, chunk_size=1024) -> None:
69
69
  resp = requests.get(url, stream=True)
70
- total = int(resp.headers.get('content-length', 0))
71
- with outfile.open('wb') as file, tqdm(
70
+ total = int(resp.headers.get("content-length", 0))
71
+ with (
72
+ outfile.open("wb") as file,
73
+ tqdm(
72
74
  desc=outfile.name,
73
75
  total=total,
74
- unit='iB',
76
+ unit="iB",
75
77
  unit_scale=True,
76
78
  unit_divisor=1024,
77
- ) as bar:
79
+ ) as bar,
80
+ ):
78
81
  for data in resp.iter_content(chunk_size=chunk_size):
79
82
  size = file.write(data)
80
83
  bar.update(size)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pymobiledevice3
3
- Version: 5.0.1
3
+ Version: 5.0.2
4
4
  Summary: Pure python3 implementation for working with iDevices (iPhone, etc...)
5
5
  Author-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>
6
6
  Maintainer-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>