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
@@ -1,7 +1,9 @@
1
1
  import asyncio
2
+ import contextlib
2
3
  from base64 import b64decode, b64encode
3
4
  from datetime import datetime
4
5
  from io import BytesIO
6
+ from typing import Optional
5
7
 
6
8
  from PIL import Image
7
9
 
@@ -27,23 +29,23 @@ class ScreenCast:
27
29
  self.device_height = 0
28
30
  self.page_scale_factor = 0
29
31
  self._run = True
30
- self.recording_task = None # type: asyncio.Task | None
32
+ self.recording_task: Optional[asyncio.Task] = None
31
33
 
32
34
  @property
33
35
  def scale(self) -> float:
34
- """ The amount screen pixels in one devtools pixel. """
36
+ """The amount screen pixels in one devtools pixel."""
35
37
  real_height = self.device_height * self.page_scale_factor
36
38
  real_width = self.device_width * self.page_scale_factor
37
39
  return min(self.max_height / real_height, self.max_width / real_width, 1) * self.page_scale_factor
38
40
 
39
41
  @property
40
42
  def scaled_width(self) -> int:
41
- """ Width of screenshot after scaling. """
43
+ """Width of screenshot after scaling."""
42
44
  return int(self.scale * self.device_width)
43
45
 
44
46
  @property
45
47
  def scaled_height(self) -> int:
46
- """ Height of screenshot after scaling. """
48
+ """Height of screenshot after scaling."""
47
49
  return int(self.scale * self.device_height)
48
50
 
49
51
  async def start(self, message_id: int):
@@ -53,26 +55,26 @@ class ScreenCast:
53
55
  """
54
56
  device_size = await self.target.evaluate_and_result(
55
57
  message_id,
56
- ('(window.innerWidth > 0 ? window.innerWidth : screen.width) + "," + '
57
- '(window.innerHeight > 0 ? window.innerHeight : screen.height) + "," + '
58
- 'window.devicePixelRatio')
58
+ (
59
+ '(window.innerWidth > 0 ? window.innerWidth : screen.width) + "," + '
60
+ '(window.innerHeight > 0 ? window.innerHeight : screen.height) + "," + '
61
+ "window.devicePixelRatio"
62
+ ),
59
63
  )
60
- self.device_width, self.device_height, self.page_scale_factor = list(map(int, device_size.split(',')))
64
+ self.device_width, self.device_height, self.page_scale_factor = list(map(int, device_size.split(",")))
61
65
  self._run = True
62
66
  self.recording_task = asyncio.create_task(self.recording_loop(message_id))
63
67
 
64
68
  async def stop(self):
65
- """ Stop sending screenshots to the devtools. """
69
+ """Stop sending screenshots to the devtools."""
66
70
  self._run = False
67
71
  self.recording_task.cancel()
68
- try:
72
+ with contextlib.suppress(asyncio.CancelledError):
69
73
  await self.recording_task
70
- except asyncio.CancelledError:
71
- pass
72
74
  self.recording_task = None
73
75
 
74
76
  def ack(self, frame_id: int):
75
- """ Handle acknowledgement for screencast frames. """
77
+ """Handle acknowledgement for screencast frames."""
76
78
  self.frames_acked.append(frame_id)
77
79
 
78
80
  def resize_jpeg(self, data: str) -> str:
@@ -83,9 +85,9 @@ class ScreenCast:
83
85
  """
84
86
  resized_img = Image.open(BytesIO(b64decode(data)))
85
87
  resized_img = resized_img.resize((self.scaled_width, self.scaled_height), Image.ANTIALIAS)
86
- resized_img = resized_img.convert('RGB')
88
+ resized_img = resized_img.convert("RGB")
87
89
  resized = BytesIO()
88
- resized_img.save(resized, format='jpeg', quality='maximum')
90
+ resized_img.save(resized, format="jpeg", quality="maximum")
89
91
  return b64encode(resized.getvalue()).decode()
90
92
 
91
93
  async def get_offsets(self, message_id: int):
@@ -96,12 +98,11 @@ class ScreenCast:
96
98
  :rtype: tuple
97
99
  """
98
100
  frame_size = await self.target.evaluate_and_result(
99
- message_id,
100
- 'window.document.body.offsetTop + "," + window.pageXOffset + "," + window.pageYOffset'
101
+ message_id, 'window.document.body.offsetTop + "," + window.pageXOffset + "," + window.pageYOffset'
101
102
  )
102
103
  if frame_size is None or not isinstance(frame_size, str):
103
104
  return 0, 0, 0
104
- return tuple(map(int, frame_size.split(',')))
105
+ return tuple(map(int, frame_size.split(",")))
105
106
 
106
107
  async def recording_loop(self, message_id):
107
108
  """
@@ -114,24 +115,32 @@ class ScreenCast:
114
115
  continue
115
116
  self.frame_id += 1
116
117
  offset_top, scroll_offset_x, scroll_offset_y = await self.get_offsets(message_id)
117
- event = await self.target.send_message_with_result(message_id, 'Page.snapshotRect', {
118
- 'x': 0, 'y': 0, 'width': self.device_width, 'height': self.device_height, 'coordinateSystem': 'Viewport'
119
- })
120
- data = event['result']['dataURL']
121
- data = data[data.find('base64,') + 7:]
118
+ event = await self.target.send_message_with_result(
119
+ message_id,
120
+ "Page.snapshotRect",
121
+ {
122
+ "x": 0,
123
+ "y": 0,
124
+ "width": self.device_width,
125
+ "height": self.device_height,
126
+ "coordinateSystem": "Viewport",
127
+ },
128
+ )
129
+ data = event["result"]["dataURL"]
130
+ data = data[data.find("base64,") + 7 :]
122
131
  await self.target.output_queue.put({
123
- 'method': 'Page.screencastFrame',
124
- 'params': {
125
- 'data': self.resize_jpeg(data),
126
- 'sessionId': self.frame_id - 1,
127
- 'metadata': {
128
- 'pageScaleFactor': self.page_scale_factor,
129
- 'offsetTop': offset_top,
130
- 'deviceWidth': self.scaled_width,
131
- 'deviceHeight': self.scaled_height,
132
- 'scrollOffsetX': scroll_offset_x,
133
- 'scrollOffsetY': scroll_offset_y,
134
- 'timestamp': datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f'),
135
- }
136
- }
132
+ "method": "Page.screencastFrame",
133
+ "params": {
134
+ "data": self.resize_jpeg(data),
135
+ "sessionId": self.frame_id - 1,
136
+ "metadata": {
137
+ "pageScaleFactor": self.page_scale_factor,
138
+ "offsetTop": offset_top,
139
+ "deviceWidth": self.scaled_width,
140
+ "deviceHeight": self.scaled_height,
141
+ "scrollOffsetX": scroll_offset_x,
142
+ "scrollOffsetY": scroll_offset_y,
143
+ "timestamp": datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f"),
144
+ },
145
+ },
137
146
  })
@@ -19,7 +19,7 @@ async def lifespan(app: FastAPI):
19
19
  app = FastAPI(lifespan=lifespan)
20
20
 
21
21
 
22
- @app.get('/json{_:path}')
22
+ @app.get("/json{_:path}")
23
23
  async def available_targets(_: str):
24
24
  app.state.inspector.get_open_pages()
25
25
  targets = []
@@ -28,47 +28,47 @@ async def available_targets(_: str):
28
28
  if page.type_ not in (WirTypes.WEB, WirTypes.WEB_PAGE):
29
29
  continue
30
30
  targets.append({
31
- 'description': '',
32
- 'id': page_id,
33
- 'title': page.web_title,
34
- 'type': 'page',
35
- 'url': page.web_url,
36
- 'webSocketDebuggerUrl': f'ws://localhost:9222/devtools/page/{page_id}',
37
- 'devtoolsFrontendUrl': f'/devtools/inspector.html?ws://localhost:9222/devtools/page/{page_id}',
31
+ "description": "",
32
+ "id": page_id,
33
+ "title": page.web_title,
34
+ "type": "page",
35
+ "url": page.web_url,
36
+ "webSocketDebuggerUrl": f"ws://localhost:9222/devtools/page/{page_id}",
37
+ "devtoolsFrontendUrl": f"/devtools/inspector.html?ws://localhost:9222/devtools/page/{page_id}",
38
38
  })
39
39
  return targets
40
40
 
41
41
 
42
- @app.get('/json/version')
42
+ @app.get("/json/version")
43
43
  def version():
44
44
  return {
45
- 'Browser': 'Safari',
46
- 'Protocol-Version': '1.1',
47
- 'User-Agent': 'pymobiledevice3',
48
- 'V8-Version': '7.2.233',
49
- 'WebKit-Version': '537.36 (@cfede9db1d154de0468cb0538479f34c0755a0f4)',
50
- 'webSocketDebuggerUrl': f'ws://localhost:9222/devtools/browser/{app.state.inspector.connection_id}'
45
+ "Browser": "Safari",
46
+ "Protocol-Version": "1.1",
47
+ "User-Agent": "pymobiledevice3",
48
+ "V8-Version": "7.2.233",
49
+ "WebKit-Version": "537.36 (@cfede9db1d154de0468cb0538479f34c0755a0f4)",
50
+ "webSocketDebuggerUrl": f"ws://localhost:9222/devtools/browser/{app.state.inspector.connection_id}",
51
51
  }
52
52
 
53
53
 
54
54
  async def from_cdp(target: CdpTarget, websocket):
55
55
  async for message in websocket.iter_json():
56
- logger.debug(f'CDP INPUT: {message}')
56
+ logger.debug(f"CDP INPUT: {message}")
57
57
  await target.send(message)
58
58
 
59
59
 
60
60
  async def to_cdp(target: CdpTarget, websocket):
61
61
  while True:
62
62
  message = await target.receive()
63
- logger.debug(f'CDP OUTPUT: {message}')
63
+ logger.debug(f"CDP OUTPUT: {message}")
64
64
  await websocket.send_json(message)
65
65
 
66
66
 
67
- @app.websocket('/devtools/page/{page_id}')
67
+ @app.websocket("/devtools/page/{page_id}")
68
68
  async def page_debugger(websocket: WebSocket, page_id: str):
69
69
  application, page = app.state.inspector.find_page_id(page_id)
70
70
  session_id = str(uuid.uuid4()).upper()
71
- protocol = SessionProtocol(app.state.inspector, session_id, application, page, method_prefix='')
71
+ protocol = SessionProtocol(app.state.inspector, session_id, application, page, method_prefix="")
72
72
  target = await CdpTarget.create(protocol)
73
73
  await websocket.accept()
74
74
  await asyncio.gather(