pymobiledevice3 4.14.6__py3-none-any.whl → 7.0.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. misc/plist_sniffer.py +15 -15
  2. misc/remotexpc_sniffer.py +29 -28
  3. misc/understanding_idevice_protocol_layers.md +15 -10
  4. pymobiledevice3/__main__.py +317 -127
  5. pymobiledevice3/_version.py +22 -4
  6. pymobiledevice3/bonjour.py +358 -113
  7. pymobiledevice3/ca.py +253 -16
  8. pymobiledevice3/cli/activation.py +31 -23
  9. pymobiledevice3/cli/afc.py +49 -40
  10. pymobiledevice3/cli/amfi.py +16 -21
  11. pymobiledevice3/cli/apps.py +87 -42
  12. pymobiledevice3/cli/backup.py +160 -90
  13. pymobiledevice3/cli/bonjour.py +44 -40
  14. pymobiledevice3/cli/cli_common.py +204 -198
  15. pymobiledevice3/cli/companion_proxy.py +14 -14
  16. pymobiledevice3/cli/crash.py +105 -56
  17. pymobiledevice3/cli/developer/__init__.py +62 -0
  18. pymobiledevice3/cli/developer/accessibility/__init__.py +65 -0
  19. pymobiledevice3/cli/developer/accessibility/settings.py +43 -0
  20. pymobiledevice3/cli/developer/arbitration.py +50 -0
  21. pymobiledevice3/cli/developer/condition.py +33 -0
  22. pymobiledevice3/cli/developer/core_device.py +294 -0
  23. pymobiledevice3/cli/developer/debugserver.py +244 -0
  24. pymobiledevice3/cli/developer/dvt/__init__.py +438 -0
  25. pymobiledevice3/cli/developer/dvt/core_profile_session.py +295 -0
  26. pymobiledevice3/cli/developer/dvt/simulate_location.py +56 -0
  27. pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +69 -0
  28. pymobiledevice3/cli/developer/dvt/sysmon/process.py +188 -0
  29. pymobiledevice3/cli/developer/fetch_symbols.py +108 -0
  30. pymobiledevice3/cli/developer/simulate_location.py +51 -0
  31. pymobiledevice3/cli/diagnostics/__init__.py +75 -0
  32. pymobiledevice3/cli/diagnostics/battery.py +47 -0
  33. pymobiledevice3/cli/idam.py +42 -0
  34. pymobiledevice3/cli/lockdown.py +108 -103
  35. pymobiledevice3/cli/mounter.py +158 -99
  36. pymobiledevice3/cli/notification.py +38 -26
  37. pymobiledevice3/cli/pcap.py +45 -24
  38. pymobiledevice3/cli/power_assertion.py +18 -17
  39. pymobiledevice3/cli/processes.py +17 -23
  40. pymobiledevice3/cli/profile.py +165 -109
  41. pymobiledevice3/cli/provision.py +35 -34
  42. pymobiledevice3/cli/remote.py +217 -129
  43. pymobiledevice3/cli/restore.py +159 -143
  44. pymobiledevice3/cli/springboard.py +63 -53
  45. pymobiledevice3/cli/syslog.py +193 -86
  46. pymobiledevice3/cli/usbmux.py +73 -33
  47. pymobiledevice3/cli/version.py +5 -7
  48. pymobiledevice3/cli/webinspector.py +376 -214
  49. pymobiledevice3/common.py +3 -1
  50. pymobiledevice3/exceptions.py +182 -58
  51. pymobiledevice3/irecv.py +52 -53
  52. pymobiledevice3/irecv_devices.py +1489 -464
  53. pymobiledevice3/lockdown.py +473 -275
  54. pymobiledevice3/lockdown_service_provider.py +15 -8
  55. pymobiledevice3/osu/os_utils.py +27 -9
  56. pymobiledevice3/osu/posix_util.py +34 -15
  57. pymobiledevice3/osu/win_util.py +14 -8
  58. pymobiledevice3/pair_records.py +102 -21
  59. pymobiledevice3/remote/common.py +8 -4
  60. pymobiledevice3/remote/core_device/app_service.py +94 -67
  61. pymobiledevice3/remote/core_device/core_device_service.py +17 -14
  62. pymobiledevice3/remote/core_device/device_info.py +5 -5
  63. pymobiledevice3/remote/core_device/diagnostics_service.py +19 -4
  64. pymobiledevice3/remote/core_device/file_service.py +53 -23
  65. pymobiledevice3/remote/remote_service_discovery.py +79 -45
  66. pymobiledevice3/remote/remotexpc.py +73 -44
  67. pymobiledevice3/remote/tunnel_service.py +442 -317
  68. pymobiledevice3/remote/utils.py +14 -13
  69. pymobiledevice3/remote/xpc_message.py +145 -125
  70. pymobiledevice3/resources/dsc_uuid_map.py +19 -19
  71. pymobiledevice3/resources/firmware_notifications.py +20 -16
  72. pymobiledevice3/resources/notifications.txt +144 -0
  73. pymobiledevice3/restore/asr.py +27 -27
  74. pymobiledevice3/restore/base_restore.py +110 -21
  75. pymobiledevice3/restore/consts.py +87 -66
  76. pymobiledevice3/restore/device.py +59 -12
  77. pymobiledevice3/restore/fdr.py +46 -48
  78. pymobiledevice3/restore/ftab.py +19 -19
  79. pymobiledevice3/restore/img4.py +163 -0
  80. pymobiledevice3/restore/mbn.py +587 -0
  81. pymobiledevice3/restore/recovery.py +151 -151
  82. pymobiledevice3/restore/restore.py +562 -544
  83. pymobiledevice3/restore/restore_options.py +131 -110
  84. pymobiledevice3/restore/restored_client.py +51 -31
  85. pymobiledevice3/restore/tss.py +385 -267
  86. pymobiledevice3/service_connection.py +252 -59
  87. pymobiledevice3/services/accessibilityaudit.py +202 -120
  88. pymobiledevice3/services/afc.py +962 -365
  89. pymobiledevice3/services/amfi.py +24 -30
  90. pymobiledevice3/services/companion.py +23 -19
  91. pymobiledevice3/services/crash_reports.py +71 -47
  92. pymobiledevice3/services/debugserver_applist.py +3 -3
  93. pymobiledevice3/services/device_arbitration.py +8 -8
  94. pymobiledevice3/services/device_link.py +101 -79
  95. pymobiledevice3/services/diagnostics.py +973 -967
  96. pymobiledevice3/services/dtfetchsymbols.py +8 -8
  97. pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +4 -4
  98. pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +4 -4
  99. pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +85 -74
  100. pymobiledevice3/services/dvt/instruments/application_listing.py +2 -3
  101. pymobiledevice3/services/dvt/instruments/condition_inducer.py +7 -6
  102. pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +466 -384
  103. pymobiledevice3/services/dvt/instruments/device_info.py +20 -11
  104. pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
  105. pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
  106. pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
  107. pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
  108. pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
  109. pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
  110. pymobiledevice3/services/dvt/instruments/process_control.py +35 -10
  111. pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
  112. pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
  113. pymobiledevice3/services/dvt/testmanaged/xcuitest.py +42 -52
  114. pymobiledevice3/services/file_relay.py +10 -10
  115. pymobiledevice3/services/heartbeat.py +9 -8
  116. pymobiledevice3/services/house_arrest.py +16 -15
  117. pymobiledevice3/services/idam.py +20 -0
  118. pymobiledevice3/services/installation_proxy.py +173 -81
  119. pymobiledevice3/services/lockdown_service.py +20 -10
  120. pymobiledevice3/services/misagent.py +22 -19
  121. pymobiledevice3/services/mobile_activation.py +147 -64
  122. pymobiledevice3/services/mobile_config.py +331 -294
  123. pymobiledevice3/services/mobile_image_mounter.py +141 -113
  124. pymobiledevice3/services/mobilebackup2.py +203 -145
  125. pymobiledevice3/services/notification_proxy.py +11 -11
  126. pymobiledevice3/services/os_trace.py +134 -74
  127. pymobiledevice3/services/pcapd.py +314 -302
  128. pymobiledevice3/services/power_assertion.py +10 -9
  129. pymobiledevice3/services/preboard.py +4 -4
  130. pymobiledevice3/services/remote_fetch_symbols.py +21 -14
  131. pymobiledevice3/services/remote_server.py +176 -146
  132. pymobiledevice3/services/restore_service.py +16 -16
  133. pymobiledevice3/services/screenshot.py +15 -12
  134. pymobiledevice3/services/simulate_location.py +7 -7
  135. pymobiledevice3/services/springboard.py +15 -15
  136. pymobiledevice3/services/syslog.py +5 -5
  137. pymobiledevice3/services/web_protocol/alert.py +11 -11
  138. pymobiledevice3/services/web_protocol/automation_session.py +251 -239
  139. pymobiledevice3/services/web_protocol/cdp_screencast.py +46 -37
  140. pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
  141. pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
  142. pymobiledevice3/services/web_protocol/driver.py +114 -111
  143. pymobiledevice3/services/web_protocol/element.py +124 -111
  144. pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
  145. pymobiledevice3/services/web_protocol/selenium_api.py +49 -49
  146. pymobiledevice3/services/web_protocol/session_protocol.py +18 -12
  147. pymobiledevice3/services/web_protocol/switch_to.py +30 -27
  148. pymobiledevice3/services/webinspector.py +189 -155
  149. pymobiledevice3/tcp_forwarder.py +87 -69
  150. pymobiledevice3/tunneld/__init__.py +0 -0
  151. pymobiledevice3/tunneld/api.py +63 -0
  152. pymobiledevice3/tunneld/server.py +603 -0
  153. pymobiledevice3/usbmux.py +198 -147
  154. pymobiledevice3/utils.py +14 -11
  155. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/METADATA +55 -28
  156. pymobiledevice3-7.0.6.dist-info/RECORD +188 -0
  157. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/WHEEL +1 -1
  158. pymobiledevice3/cli/developer.py +0 -1215
  159. pymobiledevice3/cli/diagnostics.py +0 -99
  160. pymobiledevice3/tunneld.py +0 -524
  161. pymobiledevice3-4.14.6.dist-info/RECORD +0 -168
  162. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/entry_points.txt +0 -0
  163. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info/licenses}/LICENSE +0 -0
  164. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/top_level.txt +0 -0
pymobiledevice3/irecv.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import binascii
2
+ import contextlib
2
3
  import logging
3
4
  import math
4
5
  import struct
@@ -10,7 +11,7 @@ from tqdm import trange
10
11
  from usb.core import Device, USBError, find
11
12
  from usb.util import get_string
12
13
 
13
- from pymobiledevice3.exceptions import IRecvNoDeviceConnectedError, PyMobileDevice3Exception
14
+ from pymobiledevice3.exceptions import IRecvError, IRecvNoDeviceConnectedError, PyMobileDevice3Exception
14
15
  from pymobiledevice3.irecv_devices import IRECV_DEVICES, IRecvDevice
15
16
 
16
17
  USB_TIMEOUT = 10000
@@ -28,10 +29,7 @@ class Mode(Enum):
28
29
 
29
30
  @classmethod
30
31
  def has_value(cls, value):
31
- for m in cls:
32
- if value == m.value:
33
- return True
34
- return False
32
+ return any(value == m.value for m in cls)
35
33
 
36
34
  @classmethod
37
35
  def get_mode_from_value(cls, value):
@@ -61,7 +59,7 @@ logger = logging.getLogger(__name__)
61
59
 
62
60
 
63
61
  class IRecv:
64
- def __init__(self, ecid=None, timeout=0xffffffff, is_recovery=None):
62
+ def __init__(self, ecid=None, timeout=0xFFFFFFFF, is_recovery=None):
65
63
  self.mode: Optional[Mode] = None
66
64
  self._device_info = {}
67
65
  self._device: Optional[Device] = None
@@ -69,27 +67,27 @@ class IRecv:
69
67
 
70
68
  @property
71
69
  def ecid(self):
72
- return int(self._device_info['ECID'], 16)
70
+ return int(self._device_info["ECID"], 16)
73
71
 
74
72
  @property
75
73
  def ibfl(self):
76
- return int(self._device_info['IBFL'], 16)
74
+ return int(self._device_info["IBFL"], 16)
77
75
 
78
76
  @property
79
77
  def chip_id(self):
80
- return int(self._device_info['CPID'], 16)
78
+ return int(self._device_info["CPID"], 16)
81
79
 
82
80
  @property
83
81
  def board_id(self):
84
- return int(self._device_info['BDID'], 16)
82
+ return int(self._device_info["BDID"], 16)
85
83
 
86
84
  @property
87
85
  def serial_number(self) -> int:
88
- return int(self._device_info['SRNM'], 16)
86
+ return int(self._device_info["SRNM"], 16)
89
87
 
90
88
  @property
91
89
  def iboot_version(self) -> str:
92
- return self._device_info['SRTG']
90
+ return self._device_info["SRTG"]
93
91
 
94
92
  @property
95
93
  def is_image4_supported(self):
@@ -100,7 +98,7 @@ class IRecv:
100
98
  for device in IRECV_DEVICES:
101
99
  if device.board_id == self.board_id and device.chip_id == self.chip_id:
102
100
  return device
103
- raise KeyError(f'failed to find device of: board_id: {self.board_id} chip_id: {self.chip_id}')
101
+ raise KeyError(f"failed to find device of: board_id: {self.board_id} chip_id: {self.chip_id}")
104
102
 
105
103
  @property
106
104
  def product_type(self):
@@ -116,15 +114,15 @@ class IRecv:
116
114
 
117
115
  @property
118
116
  def status(self):
119
- return self.ctrl_transfer(0xa1, 3, data_or_wLength=b'\x00' * 6)[4]
117
+ return self.ctrl_transfer(0xA1, 3, data_or_wLength=b"\x00" * 6)[4]
120
118
 
121
119
  def set_interface_altsetting(self, interface=None, alternate_setting=None):
122
- logger.debug(f'set_interface_altsetting: {interface} {alternate_setting}')
120
+ logger.debug(f"set_interface_altsetting: {interface} {alternate_setting}")
123
121
  if interface == 1:
124
122
  self._device.set_interface_altsetting(interface=interface, alternate_setting=alternate_setting)
125
123
 
126
124
  def set_configuration(self, configuration=None):
127
- logger.debug(f'set_configuration: {configuration}')
125
+ logger.debug(f"set_configuration: {configuration}")
128
126
  try:
129
127
  if self._device.get_active_configuration().bConfigurationValue == configuration:
130
128
  return
@@ -143,44 +141,44 @@ class IRecv:
143
141
  if self.mode.is_recovery:
144
142
  self.ctrl_transfer(0x41, 0)
145
143
  else:
146
- response = self.ctrl_transfer(0xa1, 5, data_or_wLength=1)
144
+ response = self.ctrl_transfer(0xA1, 5, data_or_wLength=1)
147
145
  state = response[0]
148
- logger.debug(f'irecv state: {state}')
146
+ logger.debug(f"irecv state: {state}")
149
147
  if state == 2:
150
148
  # DFU IDLE
151
149
  pass
152
150
  elif state == 10:
153
151
  self.ctrl_transfer(0x21, 4)
154
- raise PyMobileDevice3Exception('DFU ERROR, issuing CLRSTATUS')
152
+ raise PyMobileDevice3Exception("DFU ERROR, issuing CLRSTATUS")
155
153
  else:
156
154
  self.ctrl_transfer(0x21, 6)
157
- raise PyMobileDevice3Exception(f'Unexpected state {state}, issuing ABORT')
155
+ raise PyMobileDevice3Exception(f"Unexpected state {state}, issuing ABORT")
158
156
 
159
157
  crc = -1
160
158
 
161
159
  num_packets = math.ceil(len(buf) / packet_size)
162
160
 
163
- for offset in trange(0, len(buf), packet_size, dynamic_ncols=True):
161
+ for _offset in trange(0, len(buf), packet_size, dynamic_ncols=True):
164
162
  # Use bulk transfer for recovery mode and control transfer for DFU and WTF mode
165
- chunk = buf[offset:offset + packet_size]
166
- packet_index = offset // packet_size
163
+ chunk = buf[_offset : _offset + packet_size]
164
+ packet_index = _offset // packet_size
167
165
 
168
166
  if self.mode.is_recovery:
169
167
  n = self._device.write(0x04, chunk, timeout=USB_TIMEOUT)
170
168
  if n != len(chunk):
171
- raise IOError('failed to upload data')
169
+ raise OSError("failed to upload data")
172
170
  else:
173
- if offset + packet_size >= len(buf):
171
+ if _offset + packet_size >= len(buf):
174
172
  # last packet
175
173
 
176
174
  # calculate crc of all sent data
177
175
  crc = binascii.crc32(buf, crc)
178
176
 
179
177
  # add crc of dfu_xbuf (salted value)
180
- dfu_xbuf = bytearray([0xff, 0xff, 0xff, 0xff, 0xac, 0x05, 0x00, 0x01, 0x55, 0x46, 0x44, 0x10])
178
+ dfu_xbuf = bytearray([0xFF, 0xFF, 0xFF, 0xFF, 0xAC, 0x05, 0x00, 0x01, 0x55, 0x46, 0x44, 0x10])
181
179
  crc = binascii.crc32(dfu_xbuf, crc)
182
180
 
183
- crc_chunk = dfu_xbuf + struct.pack('<I', crc)
181
+ crc_chunk = dfu_xbuf + struct.pack("<I", crc)
184
182
 
185
183
  if len(chunk) + 16 > packet_size:
186
184
  # crc exceeds the max allowed packet size
@@ -192,13 +190,13 @@ class IRecv:
192
190
  self.ctrl_transfer(0x21, 1, wValue=packet_index, wIndex=0, data_or_wLength=chunk)
193
191
 
194
192
  if not self.mode.is_recovery:
195
- logger.debug('waiting for status == 5')
193
+ logger.debug("waiting for status == 5")
196
194
  while self.status != 5:
197
195
  time.sleep(1)
198
196
 
199
197
  self.ctrl_transfer(0x21, 1, wValue=num_packets, wIndex=0)
200
198
 
201
- for offset in range(2):
199
+ for _offset in range(2):
202
200
  # i know it's not used but idevicerestore does that also
203
201
  _ = self.status
204
202
 
@@ -206,8 +204,8 @@ class IRecv:
206
204
 
207
205
  def reset(self):
208
206
  try:
209
- logger.debug('resetting usb device')
210
- logger.info('If the restore hangs here, disconnect & reconnect the device')
207
+ logger.debug("resetting usb device")
208
+ logger.info("If the restore hangs here, disconnect & reconnect the device")
211
209
  self._device.reset()
212
210
  except USBError:
213
211
  pass
@@ -215,36 +213,34 @@ class IRecv:
215
213
  self._reinit(ecid=self.ecid)
216
214
 
217
215
  def send_command(self, cmd: str, timeout=USB_TIMEOUT, b_request=0):
218
- self._device.ctrl_transfer(0x40, b_request, 0, 0, cmd.encode() + b'\0', timeout=timeout)
216
+ self._device.ctrl_transfer(0x40, b_request, 0, 0, cmd.encode() + b"\0", timeout=timeout)
219
217
 
220
218
  def getenv(self, name):
221
219
  try:
222
- self.send_command(f'getenv {name}')
220
+ self.send_command(f"getenv {name}")
223
221
  except USBError:
224
222
  return None
225
- return bytearray(self._device.ctrl_transfer(0xc0, 0, 0, 0, 255))
223
+ return bytearray(self._device.ctrl_transfer(0xC0, 0, 0, 0, 255))
226
224
 
227
225
  def set_autoboot(self, enable: bool):
228
- self.send_command(f'setenv auto-boot {str(enable).lower()}')
229
- self.send_command('saveenv')
226
+ self.send_command(f"setenv auto-boot {str(enable).lower()}")
227
+ self.send_command("saveenv")
230
228
 
231
229
  def reboot(self):
232
- try:
233
- self.send_command('reboot')
234
- except USBError:
235
- pass
230
+ with contextlib.suppress(USBError):
231
+ self.send_command("reboot")
236
232
 
237
- def _reinit(self, ecid=None, timeout=0xffffffff, is_recovery=None):
233
+ def _reinit(self, ecid=None, timeout=0xFFFFFFFF, is_recovery=None):
238
234
  self._device = None
239
235
  self._device_info = {}
240
236
  self.mode = None
241
237
  self._find(ecid=ecid, timeout=timeout, is_recovery=is_recovery)
242
238
  if self._device is None:
243
- raise IRecvNoDeviceConnectedError('Failed to find a connected iDevice')
239
+ raise IRecvNoDeviceConnectedError("Failed to find a connected iDevice")
244
240
  self._populate_device_info()
245
241
 
246
- self.ap_nonce = self._copy_nonce_with_tag('NONC')
247
- self.sep_nonce = self._copy_nonce_with_tag('SNON')
242
+ self.ap_nonce = self._copy_nonce_with_tag("NONC")
243
+ self.sep_nonce = self._copy_nonce_with_tag("SNON")
248
244
 
249
245
  self.set_configuration(1)
250
246
 
@@ -256,9 +252,12 @@ class IRecv:
256
252
  self.set_interface_altsetting(0, 0)
257
253
 
258
254
  def _copy_nonce_with_tag(self, tag):
259
- return binascii.unhexlify(get_string(self._device, 1).split(f'{tag}:')[1].split(' ')[0])
255
+ if tag in get_string(self._device, 1):
256
+ return binascii.unhexlify(get_string(self._device, 1).split(f"{tag}:")[1].split(" ")[0])
257
+ else:
258
+ return None
260
259
 
261
- def _find(self, ecid=None, timeout=0xffffffff, is_recovery=None):
260
+ def _find(self, ecid=None, timeout=0xFFFFFFFF, is_recovery=None):
262
261
  start = time.time()
263
262
  end = start + timeout
264
263
  while (self._device is None) and (time.time() < end):
@@ -266,7 +265,7 @@ class IRecv:
266
265
  try:
267
266
  if device.manufacturer is None:
268
267
  continue
269
- if not device.manufacturer.startswith('Apple'):
268
+ if not device.manufacturer.startswith("Apple"):
270
269
  continue
271
270
 
272
271
  mode = Mode.get_mode_from_value(device.idProduct)
@@ -278,13 +277,13 @@ class IRecv:
278
277
  continue
279
278
 
280
279
  if self._device is not None:
281
- raise Exception('More then one connected device was found connected in recovery mode')
280
+ raise IRecvError("More then one connected device was found connected in recovery mode")
282
281
  self._device = device
283
282
  self.mode = mode
284
283
  self._populate_device_info()
285
284
 
286
285
  if ecid is not None:
287
- found_ecid = int(self._device_info['ECID'], 16)
286
+ found_ecid = int(self._device_info["ECID"], 16)
288
287
  if found_ecid != ecid:
289
288
  # wrong device - move on
290
289
  self._device = None
@@ -293,9 +292,9 @@ class IRecv:
293
292
  continue
294
293
 
295
294
  def _populate_device_info(self):
296
- for component in self._device.serial_number.split(' '):
297
- k, v = component.split(':')
298
- if k in ('SRNM', 'SRTG') and '[' in v:
295
+ for component in self._device.serial_number.split(" "):
296
+ k, v = component.split(":")
297
+ if k in ("SRNM", "SRTG") and "[" in v:
299
298
  # trim the `[]`
300
299
  v = v[1:-1]
301
300
  self._device_info[k] = v
@@ -314,5 +313,5 @@ def main():
314
313
  print(IRecv())
315
314
 
316
315
 
317
- if __name__ == '__main__':
316
+ if __name__ == "__main__":
318
317
  main()