pymobiledevice3 5.0.0__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 +466 -384
  87. pymobiledevice3/services/dvt/instruments/device_info.py +11 -11
  88. pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
  89. pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
  90. pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
  91. pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
  92. pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
  93. pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
  94. pymobiledevice3/services/dvt/instruments/process_control.py +25 -10
  95. pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
  96. pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
  97. pymobiledevice3/services/dvt/testmanaged/xcuitest.py +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.0.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.0.dist-info/RECORD +0 -173
  140. {pymobiledevice3-5.0.0.dist-info → pymobiledevice3-5.0.2.dist-info}/WHEEL +0 -0
  141. {pymobiledevice3-5.0.0.dist-info → pymobiledevice3-5.0.2.dist-info}/entry_points.txt +0 -0
  142. {pymobiledevice3-5.0.0.dist-info → pymobiledevice3-5.0.2.dist-info}/licenses/LICENSE +0 -0
  143. {pymobiledevice3-5.0.0.dist-info → pymobiledevice3-5.0.2.dist-info}/top_level.txt +0 -0
@@ -24,8 +24,13 @@ from pygments.styles import get_style_by_name
24
24
 
25
25
  from pymobiledevice3.cli.cli_common import Command
26
26
  from pymobiledevice3.common import get_home_folder
27
- from pymobiledevice3.exceptions import InspectorEvaluateError, LaunchingApplicationError, \
28
- RemoteAutomationNotEnabledError, WebInspectorNotEnabledError, WirError
27
+ from pymobiledevice3.exceptions import (
28
+ InspectorEvaluateError,
29
+ LaunchingApplicationError,
30
+ RemoteAutomationNotEnabledError,
31
+ WebInspectorNotEnabledError,
32
+ WirError,
33
+ )
29
34
  from pymobiledevice3.lockdown import LockdownClient, create_using_usbmux
30
35
  from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
31
36
  from pymobiledevice3.osu.os_utils import get_os_utils
@@ -34,7 +39,7 @@ from pymobiledevice3.services.web_protocol.driver import By, Cookie, WebDriver
34
39
  from pymobiledevice3.services.web_protocol.inspector_session import InspectorSession
35
40
  from pymobiledevice3.services.webinspector import SAFARI, ApplicationPage, WebinspectorService
36
41
 
37
- SCRIPT = '''
42
+ SCRIPT = """
38
43
  function inspectedPage_evalResult_getCompletions(primitiveType) {{
39
44
  var resultSet={{}};
40
45
  var object = primitiveType;
@@ -52,15 +57,74 @@ function inspectedPage_evalResult_getCompletions(primitiveType) {{
52
57
  try {{
53
58
  inspectedPage_evalResult_getCompletions({object})
54
59
  }} catch (e) {{}}
55
- '''
56
-
57
- JS_RESERVED_WORDS = ['abstract', 'arguments', 'await', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class',
58
- 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'double', 'else', 'enum', 'eval',
59
- 'export', 'extends', 'false', 'final', 'finally', 'float', 'for', 'function', 'goto', 'if',
60
- 'implements', 'import', 'in', 'instanceof', 'int', 'interface', 'let', 'long', 'native', 'new',
61
- 'null', 'package', 'private', 'protected', 'public', 'return', 'short', 'static', 'super',
62
- 'switch', 'synchronized', 'this', 'throw', 'throws', 'transient', 'true', 'try', 'typeof', 'var',
63
- 'void', 'volatile', 'while', 'with', 'yield', ]
60
+ """
61
+
62
+ JS_RESERVED_WORDS = [
63
+ "abstract",
64
+ "arguments",
65
+ "await",
66
+ "boolean",
67
+ "break",
68
+ "byte",
69
+ "case",
70
+ "catch",
71
+ "char",
72
+ "class",
73
+ "const",
74
+ "continue",
75
+ "debugger",
76
+ "default",
77
+ "delete",
78
+ "do",
79
+ "double",
80
+ "else",
81
+ "enum",
82
+ "eval",
83
+ "export",
84
+ "extends",
85
+ "false",
86
+ "final",
87
+ "finally",
88
+ "float",
89
+ "for",
90
+ "function",
91
+ "goto",
92
+ "if",
93
+ "implements",
94
+ "import",
95
+ "in",
96
+ "instanceof",
97
+ "int",
98
+ "interface",
99
+ "let",
100
+ "long",
101
+ "native",
102
+ "new",
103
+ "null",
104
+ "package",
105
+ "private",
106
+ "protected",
107
+ "public",
108
+ "return",
109
+ "short",
110
+ "static",
111
+ "super",
112
+ "switch",
113
+ "synchronized",
114
+ "this",
115
+ "throw",
116
+ "throws",
117
+ "transient",
118
+ "true",
119
+ "try",
120
+ "typeof",
121
+ "var",
122
+ "void",
123
+ "volatile",
124
+ "while",
125
+ "with",
126
+ "yield",
127
+ ]
64
128
 
65
129
  OSUTILS = get_os_utils()
66
130
  logger = logging.getLogger(__name__)
@@ -73,7 +137,7 @@ def cli() -> None:
73
137
 
74
138
  @cli.group()
75
139
  def webinspector() -> None:
76
- """ Access webinspector services """
140
+ """Access webinspector services"""
77
141
  pass
78
142
 
79
143
 
@@ -82,11 +146,11 @@ def catch_errors(func):
82
146
  try:
83
147
  return func(*args, **kwargs)
84
148
  except LaunchingApplicationError:
85
- logger.error('Unable to launch application (try to unlock device)')
149
+ logger.exception("Unable to launch application (try to unlock device)")
86
150
  except WebInspectorNotEnabledError:
87
- logger.error('Web inspector is not enable')
151
+ logger.exception("Web inspector is not enable")
88
152
  except RemoteAutomationNotEnabledError:
89
- logger.error('Remote automation is not enable')
153
+ logger.exception("Remote automation is not enable")
90
154
 
91
155
  return update_wrapper(catch_function, func)
92
156
 
@@ -105,7 +169,7 @@ def create_webinspector_and_launch_app(lockdown: LockdownClient, timeout: float,
105
169
 
106
170
 
107
171
  @webinspector.command(cls=Command)
108
- @click.option('-t', '--timeout', default=3, show_default=True, type=float)
172
+ @click.option("-t", "--timeout", default=3, show_default=True, type=float)
109
173
  @catch_errors
110
174
  def opened_tabs(service_provider: LockdownClient, timeout):
111
175
  """
@@ -126,8 +190,8 @@ def opened_tabs(service_provider: LockdownClient, timeout):
126
190
 
127
191
 
128
192
  @webinspector.command(cls=Command)
129
- @click.argument('url')
130
- @click.option('-t', '--timeout', default=3, show_default=True, type=float)
193
+ @click.argument("url")
194
+ @click.option("-t", "--timeout", default=3, show_default=True, type=float)
131
195
  @catch_errors
132
196
  def launch(service_provider: LockdownClient, url, timeout):
133
197
  """
@@ -146,16 +210,16 @@ def launch(service_provider: LockdownClient, url, timeout):
146
210
  inspector, safari = create_webinspector_and_launch_app(service_provider, timeout, SAFARI)
147
211
  session = inspector.automation_session(safari)
148
212
  driver = WebDriver(session)
149
- print('Starting session')
213
+ print("Starting session")
150
214
  driver.start_session()
151
- print('Getting URL')
215
+ print("Getting URL")
152
216
  driver.get(url)
153
217
  OSUTILS.wait_return()
154
218
  session.stop_session()
155
219
  inspector.close()
156
220
 
157
221
 
158
- SHELL_USAGE = '''
222
+ SHELL_USAGE = """
159
223
  # This shell allows you to control the web with selenium like API.
160
224
  # The first thing you should do is creating a session:
161
225
  driver.start_session()
@@ -173,11 +237,11 @@ driver.add_cookie(
173
237
  )
174
238
 
175
239
  # See selenium api for more features.
176
- '''
240
+ """
177
241
 
178
242
 
179
243
  @webinspector.command(cls=Command)
180
- @click.option('-t', '--timeout', default=3, show_default=True, type=float)
244
+ @click.option("-t", "--timeout", default=3, show_default=True, type=float)
181
245
  @catch_errors
182
246
  def shell(service_provider: LockdownClient, timeout):
183
247
  """
@@ -197,25 +261,27 @@ def shell(service_provider: LockdownClient, timeout):
197
261
  driver = WebDriver(session)
198
262
  try:
199
263
  IPython.embed(
200
- header=highlight(SHELL_USAGE, lexers.PythonLexer(), formatters.Terminal256Formatter(style='native')),
264
+ header=highlight(SHELL_USAGE, lexers.PythonLexer(), formatters.Terminal256Formatter(style="native")),
201
265
  user_ns={
202
- 'driver': driver,
203
- 'Cookie': Cookie,
204
- 'By': By,
205
- })
266
+ "driver": driver,
267
+ "Cookie": Cookie,
268
+ "By": By,
269
+ },
270
+ )
206
271
  finally:
207
272
  session.stop_session()
208
273
  inspector.close()
209
274
 
210
275
 
211
276
  @webinspector.command(cls=Command)
212
- @click.option('-t', '--timeout', default=3, show_default=True, type=float)
213
- @click.option('--automation', is_flag=True, help='Use remote automation')
214
- @click.option('--no-open-safari', is_flag=True, help='Avoid opening the Safari app')
215
- @click.argument('url', required=False, default='')
277
+ @click.option("-t", "--timeout", default=3, show_default=True, type=float)
278
+ @click.option("--automation", is_flag=True, help="Use remote automation")
279
+ @click.option("--no-open-safari", is_flag=True, help="Avoid opening the Safari app")
280
+ @click.argument("url", required=False, default="")
216
281
  @catch_errors
217
- def js_shell(service_provider: LockdownServiceProvider, timeout: float, automation: bool, no_open_safari: bool,
218
- url: str) -> None:
282
+ def js_shell(
283
+ service_provider: LockdownServiceProvider, timeout: float, automation: bool, no_open_safari: bool, url: str
284
+ ) -> None:
219
285
  """
220
286
  Create a javascript shell. This interpreter runs on your local machine,
221
287
  but evaluates each expression on the remote
@@ -234,7 +300,7 @@ def js_shell(service_provider: LockdownServiceProvider, timeout: float, automati
234
300
  asyncio.run(run_js_shell(js_shell_class, service_provider, timeout, url, not no_open_safari))
235
301
 
236
302
 
237
- udid = ''
303
+ udid = ""
238
304
 
239
305
 
240
306
  def create_app():
@@ -244,8 +310,8 @@ def create_app():
244
310
 
245
311
 
246
312
  @webinspector.command(cls=Command)
247
- @click.option('--host', default='127.0.0.1')
248
- @click.option('--port', type=click.INT, default=9222)
313
+ @click.option("--host", default="127.0.0.1")
314
+ @click.option("--port", type=click.INT, default=9222)
249
315
  def cdp(service_provider: LockdownClient, host, port):
250
316
  """
251
317
  Start a CDP server for debugging WebViews.
@@ -256,18 +322,26 @@ def cdp(service_provider: LockdownClient, host, port):
256
322
  """
257
323
  global udid
258
324
  udid = service_provider.udid
259
- uvicorn.run('pymobiledevice3.cli.webinspector:create_app', host=host, port=port, factory=True,
260
- ws_ping_timeout=None, ws='wsproto', loop='asyncio')
261
-
262
-
263
- def get_js_completions(jsshell: 'JsShell', obj: str, prefix: str) -> list[Completion]:
325
+ uvicorn.run(
326
+ "pymobiledevice3.cli.webinspector:create_app",
327
+ host=host,
328
+ port=port,
329
+ factory=True,
330
+ ws_ping_timeout=None,
331
+ ws="wsproto",
332
+ loop="asyncio",
333
+ )
334
+
335
+
336
+ def get_js_completions(jsshell: "JsShell", obj: str, prefix: str) -> list[Completion]:
264
337
  if obj in JS_RESERVED_WORDS:
265
338
  return []
266
339
 
267
340
  completions = []
268
341
  try:
269
342
  for key in asyncio.get_running_loop().run_until_complete(
270
- jsshell.evaluate_expression(SCRIPT.format(object=obj), return_by_value=True)):
343
+ jsshell.evaluate_expression(SCRIPT.format(object=obj), return_by_value=True)
344
+ ):
271
345
  if not key.startswith(prefix):
272
346
  continue
273
347
  completions.append(Completion(key.removeprefix(prefix), display=key))
@@ -278,22 +352,20 @@ def get_js_completions(jsshell: 'JsShell', obj: str, prefix: str) -> list[Comple
278
352
 
279
353
 
280
354
  class JsShellCompleter(Completer):
281
- def __init__(self, jsshell: 'JsShell'):
355
+ def __init__(self, jsshell: "JsShell"):
282
356
  self.jsshell = jsshell
283
357
 
284
- def get_completions(
285
- self, document: Document, complete_event: CompleteEvent
286
- ) -> Iterable[Completion]:
287
- text = f'globalThis.{document.text_before_cursor}'
288
- text = re.findall('[a-zA-Z_][a-zA-Z_0-9.]+', text)
358
+ def get_completions(self, document: Document, complete_event: CompleteEvent) -> Iterable[Completion]:
359
+ text = f"globalThis.{document.text_before_cursor}"
360
+ text = re.findall("[a-zA-Z_][a-zA-Z_0-9.]+", text)
289
361
  if len(text) == 0:
290
362
  return []
291
363
  text = text[-1]
292
- if '.' in text:
293
- js_obj, prefix = text.rsplit('.', 1)
364
+ if "." in text:
365
+ js_obj, prefix = text.rsplit(".", 1)
294
366
  else:
295
367
  js_obj = text
296
- prefix = ''
368
+ prefix = ""
297
369
 
298
370
  return get_js_completions(self.jsshell, js_obj, prefix)
299
371
 
@@ -301,11 +373,13 @@ class JsShellCompleter(Completer):
301
373
  class JsShell(ABC):
302
374
  def __init__(self) -> None:
303
375
  super().__init__()
304
- self.prompt_session = PromptSession(lexer=PygmentsLexer(lexers.JavascriptLexer),
305
- auto_suggest=AutoSuggestFromHistory(),
306
- style=style_from_pygments_cls(get_style_by_name('stata-dark')),
307
- history=FileHistory(self.webinspector_history_path()),
308
- completer=JsShellCompleter(self))
376
+ self.prompt_session = PromptSession(
377
+ lexer=PygmentsLexer(lexers.JavascriptLexer),
378
+ auto_suggest=AutoSuggestFromHistory(),
379
+ style=style_from_pygments_cls(get_style_by_name("stata-dark")),
380
+ history=FileHistory(self.webinspector_history_path()),
381
+ completer=JsShellCompleter(self),
382
+ )
309
383
 
310
384
  @classmethod
311
385
  @abstractmethod
@@ -328,20 +402,19 @@ class JsShell(ABC):
328
402
  return
329
403
 
330
404
  result = await self.evaluate_expression(exp)
331
- colorful_result = highlight(f'{result}', lexers.JavascriptLexer(),
332
- formatters.Terminal256Formatter(style='stata-dark'))
333
- print(colorful_result, end='')
405
+ colorful_result = highlight(
406
+ f"{result}", lexers.JavascriptLexer(), formatters.Terminal256Formatter(style="stata-dark")
407
+ )
408
+ print(colorful_result, end="")
334
409
 
335
- async def start(self, url: str = ''):
410
+ async def start(self, url: str = ""):
336
411
  if url:
337
412
  await self.navigate(url)
338
413
  while True:
339
414
  try:
340
415
  await self.js_iter()
341
- except WirError as e:
342
- logger.error(e)
343
- except InspectorEvaluateError as e:
344
- logger.error(e)
416
+ except (WirError, InspectorEvaluateError):
417
+ logger.exception("Failed in js_iter")
345
418
  except KeyboardInterrupt: # KeyboardInterrupt Control-C
346
419
  pass
347
420
  except EOFError: # Control-D
@@ -349,7 +422,7 @@ class JsShell(ABC):
349
422
 
350
423
  @staticmethod
351
424
  def webinspector_history_path() -> str:
352
- return str(get_home_folder() / 'webinspector_history')
425
+ return str(get_home_folder() / "webinspector_history")
353
426
 
354
427
 
355
428
  class AutomationJsShell(JsShell):
@@ -359,7 +432,7 @@ class AutomationJsShell(JsShell):
359
432
 
360
433
  @classmethod
361
434
  @asynccontextmanager
362
- async def create(cls, lockdown: LockdownClient, timeout: float, open_safari: bool) -> 'AutomationJsShell':
435
+ async def create(cls, lockdown: LockdownClient, timeout: float, open_safari: bool) -> "AutomationJsShell":
363
436
  inspector, application = create_webinspector_and_launch_app(lockdown, timeout, SAFARI)
364
437
  automation_session = inspector.automation_session(application)
365
438
  driver = WebDriver(automation_session)
@@ -371,7 +444,7 @@ class AutomationJsShell(JsShell):
371
444
  inspector.close()
372
445
 
373
446
  async def evaluate_expression(self, exp: str, return_by_value: bool = False):
374
- return self.driver.execute_script(f'return {exp}')
447
+ return self.driver.execute_script(f"return {exp}")
375
448
 
376
449
  async def navigate(self, url: str):
377
450
  self.driver.get(url)
@@ -384,7 +457,7 @@ class InspectorJsShell(JsShell):
384
457
 
385
458
  @classmethod
386
459
  @asynccontextmanager
387
- async def create(cls, lockdown: LockdownClient, timeout: float, open_safari: bool) -> 'InspectorJsShell':
460
+ async def create(cls, lockdown: LockdownClient, timeout: float, open_safari: bool) -> "InspectorJsShell":
388
461
  inspector = WebinspectorService(lockdown=lockdown)
389
462
  inspector.connect(timeout)
390
463
  if open_safari:
@@ -409,22 +482,27 @@ class InspectorJsShell(JsShell):
409
482
  await self.inspector_session.navigate_to_url(url)
410
483
 
411
484
  @staticmethod
412
- def query_page(inspector: WebinspectorService, bundle_identifier: Optional[str] = None) \
413
- -> Optional[ApplicationPage]:
485
+ def query_page(
486
+ inspector: WebinspectorService, bundle_identifier: Optional[str] = None
487
+ ) -> Optional[ApplicationPage]:
414
488
  available_pages = inspector.get_open_application_pages(timeout=1)
415
489
  if bundle_identifier is not None:
416
- available_pages = [application_page for application_page in available_pages if
417
- application_page.application.bundle == bundle_identifier]
490
+ available_pages = [
491
+ application_page
492
+ for application_page in available_pages
493
+ if application_page.application.bundle == bundle_identifier
494
+ ]
418
495
  if not available_pages:
419
- logger.error('Unable to find available pages (try to unlock device)')
496
+ logger.error("Unable to find available pages (try to unlock device)")
420
497
  return None
421
498
 
422
- page_query = [inquirer3.List('page', message='choose page', choices=available_pages, carousel=True)]
423
- page = inquirer3.prompt(page_query, theme=GreenPassion(), raise_keyboard_interrupt=True)['page']
499
+ page_query = [inquirer3.List("page", message="choose page", choices=available_pages, carousel=True)]
500
+ page = inquirer3.prompt(page_query, theme=GreenPassion(), raise_keyboard_interrupt=True)["page"]
424
501
  return page
425
502
 
426
503
 
427
- async def run_js_shell(js_shell_class: type[JsShell], lockdown: LockdownServiceProvider,
428
- timeout: float, url: str, open_safari: bool) -> None:
504
+ async def run_js_shell(
505
+ js_shell_class: type[JsShell], lockdown: LockdownServiceProvider, timeout: float, url: str, open_safari: bool
506
+ ) -> None:
429
507
  async with js_shell_class.create(lockdown, timeout, open_safari) as js_shell_instance:
430
508
  await js_shell_instance.start(url)
pymobiledevice3/common.py CHANGED
@@ -3,7 +3,7 @@ from pathlib import Path
3
3
  from pymobiledevice3.osu.os_utils import get_os_utils
4
4
 
5
5
  _OS_UTILS = get_os_utils()
6
- _HOMEFOLDER = _OS_UTILS.get_homedir() / '.pymobiledevice3'
6
+ _HOMEFOLDER = _OS_UTILS.get_homedir() / ".pymobiledevice3"
7
7
 
8
8
 
9
9
  def get_home_folder() -> Path: