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
@@ -18,88 +18,93 @@ def cli() -> None:
18
18
 
19
19
  @cli.group()
20
20
  def diagnostics() -> None:
21
- """ Reboot/Shutdown device or access other diagnostics services """
21
+ """Reboot/Shutdown device or access other diagnostics services"""
22
22
  pass
23
23
 
24
24
 
25
- @diagnostics.command('restart', cls=Command)
26
- @click.option('-r', '--reconnect', is_flag=True, default=False,
27
- help='Wait until the device reconnects before finishing the operation.')
25
+ @diagnostics.command("restart", cls=Command)
26
+ @click.option(
27
+ "-r",
28
+ "--reconnect",
29
+ is_flag=True,
30
+ default=False,
31
+ help="Wait until the device reconnects before finishing the operation.",
32
+ )
28
33
  def diagnostics_restart(service_provider: LockdownClient, reconnect):
29
- """ Restart device """
34
+ """Restart device"""
30
35
  DiagnosticsService(lockdown=service_provider).restart()
31
36
  if reconnect:
32
37
  # Wait for the device to be available again
33
38
  with retry_create_using_usbmux(None, serial=service_provider.udid):
34
- print(f'Device Reconnected ({service_provider.udid}).')
39
+ print(f"Device Reconnected ({service_provider.udid}).")
35
40
 
36
41
 
37
- @diagnostics.command('shutdown', cls=Command)
42
+ @diagnostics.command("shutdown", cls=Command)
38
43
  def diagnostics_shutdown(service_provider: LockdownClient):
39
- """ Shutdown device """
44
+ """Shutdown device"""
40
45
  DiagnosticsService(lockdown=service_provider).shutdown()
41
46
 
42
47
 
43
- @diagnostics.command('sleep', cls=Command)
48
+ @diagnostics.command("sleep", cls=Command)
44
49
  def diagnostics_sleep(service_provider: LockdownClient):
45
- """ Put device into sleep """
50
+ """Put device into sleep"""
46
51
  DiagnosticsService(lockdown=service_provider).sleep()
47
52
 
48
53
 
49
- @diagnostics.command('info', cls=Command)
54
+ @diagnostics.command("info", cls=Command)
50
55
  def diagnostics_info(service_provider: LockdownClient):
51
- """ Get diagnostics info """
56
+ """Get diagnostics info"""
52
57
  print_json(DiagnosticsService(lockdown=service_provider).info())
53
58
 
54
59
 
55
- @diagnostics.command('ioregistry', cls=Command)
56
- @click.option('--plane')
57
- @click.option('--name')
58
- @click.option('--ioclass')
60
+ @diagnostics.command("ioregistry", cls=Command)
61
+ @click.option("--plane")
62
+ @click.option("--name")
63
+ @click.option("--ioclass")
59
64
  def diagnostics_ioregistry(service_provider: LockdownClient, plane, name, ioclass):
60
- """ Get ioregistry info """
65
+ """Get ioregistry info"""
61
66
  print_json(DiagnosticsService(lockdown=service_provider).ioregistry(plane=plane, name=name, ioclass=ioclass))
62
67
 
63
68
 
64
- @diagnostics.command('mg', cls=Command)
65
- @click.argument('keys', nargs=-1, default=None)
69
+ @diagnostics.command("mg", cls=Command)
70
+ @click.argument("keys", nargs=-1, default=None)
66
71
  def diagnostics_mg(service_provider: LockdownClient, keys):
67
- """ Get MobileGestalt key values from given list. If empty, return all known. """
72
+ """Get MobileGestalt key values from given list. If empty, return all known."""
68
73
  print_json(DiagnosticsService(lockdown=service_provider).mobilegestalt(keys=keys))
69
74
 
70
75
 
71
- @diagnostics.group('battery')
76
+ @diagnostics.group("battery")
72
77
  def diagnostics_battery():
73
- """ Battery options """
78
+ """Battery options"""
74
79
  pass
75
80
 
76
81
 
77
- @diagnostics_battery.command('single', cls=Command)
82
+ @diagnostics_battery.command("single", cls=Command)
78
83
  def diagnostics_battery_single(service_provider: LockdownClient):
79
- """ get single snapshot of battery data """
84
+ """get single snapshot of battery data"""
80
85
  raw_info = DiagnosticsService(lockdown=service_provider).get_battery()
81
86
  print_json(raw_info)
82
87
 
83
88
 
84
- @diagnostics_battery.command('monitor', cls=Command)
89
+ @diagnostics_battery.command("monitor", cls=Command)
85
90
  def diagnostics_battery_monitor(service_provider: LockdownClient):
86
- """ monitor battery usage """
91
+ """monitor battery usage"""
87
92
  diagnostics = DiagnosticsService(lockdown=service_provider)
88
93
  while True:
89
94
  raw_info = diagnostics.get_battery()
90
95
  info = {
91
- 'InstantAmperage': raw_info.get('InstantAmperage'),
92
- 'Temperature': raw_info.get('Temperature'),
93
- 'Voltage': raw_info.get('Voltage'),
94
- 'IsCharging': raw_info.get('IsCharging'),
95
- 'CurrentCapacity': raw_info.get('CurrentCapacity'),
96
+ "InstantAmperage": raw_info.get("InstantAmperage"),
97
+ "Temperature": raw_info.get("Temperature"),
98
+ "Voltage": raw_info.get("Voltage"),
99
+ "IsCharging": raw_info.get("IsCharging"),
100
+ "CurrentCapacity": raw_info.get("CurrentCapacity"),
96
101
  }
97
102
  logger.info(info)
98
103
  time.sleep(1)
99
104
 
100
105
 
101
- @diagnostics.command('wifi', cls=Command)
106
+ @diagnostics.command("wifi", cls=Command)
102
107
  def diagnostics_wifi(service_provider: LockdownServiceProvider) -> None:
103
- """ Query WiFi info from IORegistry """
108
+ """Query WiFi info from IORegistry"""
104
109
  raw_info = DiagnosticsService(lockdown=service_provider).get_wifi()
105
110
  print_json(raw_info)
@@ -22,169 +22,174 @@ def cli() -> None:
22
22
  pass
23
23
 
24
24
 
25
- @cli.group('lockdown')
25
+ @cli.group("lockdown")
26
26
  def lockdown_group() -> None:
27
- """ Pair/Unpair device or access other lockdown services """
27
+ """Pair/Unpair device or access other lockdown services"""
28
28
  pass
29
29
 
30
30
 
31
- @lockdown_group.command('recovery', cls=Command)
31
+ @lockdown_group.command("recovery", cls=Command)
32
32
  def lockdown_recovery(service_provider: LockdownClient):
33
- """ enter recovery """
33
+ """enter recovery"""
34
34
  print_json(service_provider.enter_recovery())
35
35
 
36
36
 
37
- @lockdown_group.command('service', cls=Command)
38
- @click.argument('service_name')
37
+ @lockdown_group.command("service", cls=Command)
38
+ @click.argument("service_name")
39
39
  def lockdown_service(service_provider: LockdownServiceProvider, service_name):
40
- """ send-receive raw service messages with a given service name"""
40
+ """send-receive raw service messages with a given service name"""
41
41
  service_provider.start_lockdown_service(service_name).shell()
42
42
 
43
43
 
44
- @lockdown_group.command('developer-service', cls=Command)
45
- @click.argument('service_name')
44
+ @lockdown_group.command("developer-service", cls=Command)
45
+ @click.argument("service_name")
46
46
  def lockdown_developer_service(service_provider: LockdownServiceProvider, service_name):
47
- """ send-receive raw service messages with a given developer service name """
47
+ """send-receive raw service messages with a given developer service name"""
48
48
  service_provider.start_lockdown_developer_service(service_name).shell()
49
49
 
50
50
 
51
- @lockdown_group.command('info', cls=Command)
51
+ @lockdown_group.command("info", cls=Command)
52
52
  def lockdown_info(service_provider: LockdownServiceProvider):
53
- """ query all lockdown values """
53
+ """query all lockdown values"""
54
54
  print_json(service_provider.all_values)
55
55
 
56
56
 
57
- @lockdown_group.command('get', cls=Command)
58
- @click.argument('domain', required=False)
59
- @click.argument('key', required=False)
57
+ @lockdown_group.command("get", cls=Command)
58
+ @click.argument("domain", required=False)
59
+ @click.argument("key", required=False)
60
60
  def lockdown_get(service_provider: LockdownClient, domain, key):
61
- """ query lockdown values by their domain and key names """
61
+ """query lockdown values by their domain and key names"""
62
62
  print_json(service_provider.get_value(domain=domain, key=key))
63
63
 
64
64
 
65
- @lockdown_group.command('set', cls=Command)
66
- @click.argument('value')
67
- @click.argument('domain', required=False)
68
- @click.argument('key', required=False)
65
+ @lockdown_group.command("set", cls=Command)
66
+ @click.argument("value")
67
+ @click.argument("domain", required=False)
68
+ @click.argument("key", required=False)
69
69
  def lockdown_set(service_provider: LockdownClient, value, domain, key):
70
- """ set a lockdown value using python's eval() """
70
+ """set a lockdown value using python's eval()"""
71
71
  print_json(service_provider.set_value(value=eval(value), domain=domain, key=key))
72
72
 
73
73
 
74
- @lockdown_group.command('remove', cls=Command)
75
- @click.argument('domain')
76
- @click.argument('key')
74
+ @lockdown_group.command("remove", cls=Command)
75
+ @click.argument("domain")
76
+ @click.argument("key")
77
77
  def lockdown_remove(service_provider: LockdownClient, domain, key):
78
- """ remove a domain/key pair """
78
+ """remove a domain/key pair"""
79
79
  print_json(service_provider.remove_value(domain=domain, key=key))
80
80
 
81
81
 
82
- @lockdown_group.command('unpair', cls=CommandWithoutAutopair)
83
- @click.argument('host_id', required=False)
84
- def lockdown_unpair(service_provider: LockdownClient, host_id: str = None):
85
- """ unpair from connected device """
82
+ @lockdown_group.command("unpair", cls=CommandWithoutAutopair)
83
+ @click.argument("host_id", required=False)
84
+ def lockdown_unpair(service_provider: LockdownClient, host_id: Optional[str] = None):
85
+ """unpair from connected device"""
86
86
  service_provider.unpair(host_id=host_id)
87
87
 
88
88
 
89
- @lockdown_group.command('pair', cls=CommandWithoutAutopair)
89
+ @lockdown_group.command("pair", cls=CommandWithoutAutopair)
90
90
  def lockdown_pair(service_provider: LockdownClient):
91
- """ pair device """
91
+ """pair device"""
92
92
  service_provider.pair()
93
93
 
94
94
 
95
- @lockdown_group.command('pair-supervised', cls=CommandWithoutAutopair)
96
- @click.argument('keybag', type=click.Path(file_okay=True, dir_okay=False, exists=True))
95
+ @lockdown_group.command("pair-supervised", cls=CommandWithoutAutopair)
96
+ @click.argument("keybag", type=click.Path(file_okay=True, dir_okay=False, exists=True))
97
97
  def lockdown_pair_supervised(service_provider: LockdownClient, keybag: str) -> None:
98
- """ pair supervised device """
98
+ """pair supervised device"""
99
99
  service_provider.pair_supervised(Path(keybag))
100
100
 
101
101
 
102
- @lockdown_group.command('save-pair-record', cls=CommandWithoutAutopair)
103
- @click.argument('output', type=click.File('wb'))
102
+ @lockdown_group.command("save-pair-record", cls=CommandWithoutAutopair)
103
+ @click.argument("output", type=click.File("wb"))
104
104
  def lockdown_save_pair_record(service_provider: LockdownClient, output):
105
- """ save pair record to specified location """
105
+ """save pair record to specified location"""
106
106
  if service_provider.pair_record is None:
107
- logger.error('no pairing record was found')
107
+ logger.error("no pairing record was found")
108
108
  return
109
109
  plistlib.dump(service_provider.pair_record, output)
110
110
 
111
111
 
112
- @lockdown_group.command('date', cls=Command)
112
+ @lockdown_group.command("date", cls=Command)
113
113
  def lockdown_date(service_provider: LockdownClient):
114
- """ get device date """
114
+ """get device date"""
115
115
  print(service_provider.date)
116
116
 
117
117
 
118
- @lockdown_group.command('heartbeat', cls=Command)
118
+ @lockdown_group.command("heartbeat", cls=Command)
119
119
  def lockdown_heartbeat(service_provider: LockdownClient):
120
- """ start heartbeat service """
120
+ """start heartbeat service"""
121
121
  HeartbeatService(service_provider).start()
122
122
 
123
123
 
124
- @lockdown_group.command('language', cls=Command)
125
- @click.argument('language', required=False)
124
+ @lockdown_group.command("language", cls=Command)
125
+ @click.argument("language", required=False)
126
126
  def lockdown_language(service_provider: LockdownClient, language: Optional[str]) -> None:
127
- """ Get/Set current language settings """
127
+ """Get/Set current language settings"""
128
128
  if language is not None:
129
129
  service_provider.set_language(language)
130
130
  print_json(service_provider.language)
131
131
 
132
132
 
133
- @lockdown_group.command('locale', cls=Command)
134
- @click.argument('locale', required=False)
133
+ @lockdown_group.command("locale", cls=Command)
134
+ @click.argument("locale", required=False)
135
135
  def lockdown_locale(service_provider: LockdownClient, locale: Optional[str]) -> None:
136
- """ Get/Set current language settings """
136
+ """Get/Set current language settings"""
137
137
  if locale is not None:
138
138
  service_provider.set_locale(locale)
139
139
  print_json(service_provider.locale)
140
140
 
141
141
 
142
- @lockdown_group.command('device-name', cls=Command)
143
- @click.argument('new_name', required=False)
142
+ @lockdown_group.command("device-name", cls=Command)
143
+ @click.argument("new_name", required=False)
144
144
  def lockdown_device_name(service_provider: LockdownClient, new_name):
145
- """ get/set current device name """
145
+ """get/set current device name"""
146
146
  if new_name:
147
- service_provider.set_value(new_name, key='DeviceName')
147
+ service_provider.set_value(new_name, key="DeviceName")
148
148
  else:
149
- print(f'{service_provider.get_value(key="DeviceName")}')
149
+ print(f"{service_provider.get_value(key='DeviceName')}")
150
150
 
151
151
 
152
- @lockdown_group.command('wifi-connections', cls=Command)
153
- @click.argument('state', type=click.Choice(['on', 'off']), required=False)
152
+ @lockdown_group.command("wifi-connections", cls=Command)
153
+ @click.argument("state", type=click.Choice(["on", "off"]), required=False)
154
154
  def lockdown_wifi_connections(service_provider: LockdownClient, state):
155
- """ get/set wifi connections state """
155
+ """get/set wifi connections state"""
156
156
  if not state:
157
157
  # show current state
158
- print_json(service_provider.get_value(domain='com.apple.mobile.wireless_lockdown'))
158
+ print_json(service_provider.get_value(domain="com.apple.mobile.wireless_lockdown"))
159
159
  else:
160
160
  # enable/disable
161
- service_provider.enable_wifi_connections = state == 'on'
161
+ service_provider.enable_wifi_connections = state == "on"
162
162
 
163
163
 
164
- async def async_cli_start_tunnel(
165
- service_provider: LockdownServiceProvider, script_mode: bool) -> None:
166
- await tunnel_task(await CoreDeviceTunnelProxy.create(service_provider),
167
- script_mode=script_mode, secrets=None, protocol=TunnelProtocol.TCP)
164
+ async def async_cli_start_tunnel(service_provider: LockdownServiceProvider, script_mode: bool) -> None:
165
+ await tunnel_task(
166
+ await CoreDeviceTunnelProxy.create(service_provider),
167
+ script_mode=script_mode,
168
+ secrets=None,
169
+ protocol=TunnelProtocol.TCP,
170
+ )
168
171
 
169
172
 
170
- @lockdown_group.command('start-tunnel', cls=Command)
171
- @click.option('--script-mode', is_flag=True,
172
- help='Show only HOST and port number to allow easy parsing from external shell scripts')
173
+ @lockdown_group.command("start-tunnel", cls=Command)
174
+ @click.option(
175
+ "--script-mode",
176
+ is_flag=True,
177
+ help="Show only HOST and port number to allow easy parsing from external shell scripts",
178
+ )
173
179
  @sudo_required
174
- def cli_start_tunnel(
175
- service_provider: LockdownServiceProvider, script_mode: bool) -> None:
176
- """ start tunnel """
180
+ def cli_start_tunnel(service_provider: LockdownServiceProvider, script_mode: bool) -> None:
181
+ """start tunnel"""
177
182
  asyncio.run(async_cli_start_tunnel(service_provider, script_mode), debug=True)
178
183
 
179
184
 
180
- @lockdown_group.command('assistive-touch', cls=Command)
181
- @click.argument('state', type=click.Choice(['on', 'off']), required=False)
185
+ @lockdown_group.command("assistive-touch", cls=Command)
186
+ @click.argument("state", type=click.Choice(["on", "off"]), required=False)
182
187
  def lockdown_assistive_touch(service_provider: LockdownClient, state: str) -> None:
183
- """ get/set assistive touch icon state (visibility) """
188
+ """get/set assistive touch icon state (visibility)"""
184
189
  if not state:
185
- key = 'AssistiveTouchEnabledByiTunes'
186
- accessibility_values = service_provider.get_value('com.apple.Accessibility')
190
+ key = "AssistiveTouchEnabledByiTunes"
191
+ accessibility_values = service_provider.get_value("com.apple.Accessibility")
187
192
  print_json({key: bool(accessibility_values[key])})
188
193
  else:
189
194
  # enable/disable
190
- service_provider.assistive_touch = state == 'on'
195
+ service_provider.assistive_touch = state == "on"
@@ -7,12 +7,20 @@ from urllib.error import URLError
7
7
  import click
8
8
 
9
9
  from pymobiledevice3.cli.cli_common import Command, print_json
10
- from pymobiledevice3.exceptions import AlreadyMountedError, DeveloperDiskImageNotFoundError, NotMountedError, \
11
- UnsupportedCommandError
10
+ from pymobiledevice3.exceptions import (
11
+ AlreadyMountedError,
12
+ DeveloperDiskImageNotFoundError,
13
+ NotMountedError,
14
+ UnsupportedCommandError,
15
+ )
12
16
  from pymobiledevice3.lockdown import LockdownClient
13
17
  from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
14
- from pymobiledevice3.services.mobile_image_mounter import DeveloperDiskImageMounter, MobileImageMounterService, \
15
- PersonalizedImageMounter, auto_mount
18
+ from pymobiledevice3.services.mobile_image_mounter import (
19
+ DeveloperDiskImageMounter,
20
+ MobileImageMounterService,
21
+ PersonalizedImageMounter,
22
+ auto_mount,
23
+ )
16
24
 
17
25
  logger = logging.getLogger(__name__)
18
26
 
@@ -22,9 +30,9 @@ def catch_errors(func):
22
30
  try:
23
31
  return func(*args, **kwargs)
24
32
  except AlreadyMountedError:
25
- logger.error('Given image was already mounted')
33
+ logger.exception("Given image was already mounted")
26
34
  except UnsupportedCommandError:
27
- logger.error('Your iOS version doesn\'t support this command')
35
+ logger.exception("Your iOS version doesn't support this command")
28
36
 
29
37
  return update_wrapper(catch_function, func)
30
38
 
@@ -36,147 +44,156 @@ def cli() -> None:
36
44
 
37
45
  @cli.group()
38
46
  def mounter() -> None:
39
- """ Mount/Umount DeveloperDiskImage or query related info """
47
+ """Mount/Umount DeveloperDiskImage or query related info"""
40
48
  pass
41
49
 
42
50
 
43
- @mounter.command('list', cls=Command)
51
+ @mounter.command("list", cls=Command)
44
52
  def mounter_list(service_provider: LockdownClient):
45
- """ list all mounted images """
53
+ """list all mounted images"""
46
54
  output = []
47
55
 
48
56
  images = MobileImageMounterService(lockdown=service_provider).copy_devices()
49
57
  for image in images:
50
- image_signature = image.get('ImageSignature')
58
+ image_signature = image.get("ImageSignature")
51
59
  if image_signature is not None:
52
- image['ImageSignature'] = image_signature.hex()
60
+ image["ImageSignature"] = image_signature.hex()
53
61
  output.append(image)
54
62
 
55
63
  print_json(output)
56
64
 
57
65
 
58
- @mounter.command('lookup', cls=Command)
59
- @click.argument('image_type')
66
+ @mounter.command("lookup", cls=Command)
67
+ @click.argument("image_type")
60
68
  def mounter_lookup(service_provider: LockdownClient, image_type):
61
- """ lookup mounter image type """
69
+ """lookup mounter image type"""
62
70
  try:
63
71
  signature = MobileImageMounterService(lockdown=service_provider).lookup_image(image_type)
64
72
  print_json(signature)
65
73
  except NotMountedError:
66
- logger.error(f'Disk image of type: {image_type} is not mounted')
74
+ logger.exception(f"Disk image of type: {image_type} is not mounted")
67
75
 
68
76
 
69
- @mounter.command('umount-developer', cls=Command)
77
+ @mounter.command("umount-developer", cls=Command)
70
78
  @catch_errors
71
79
  def mounter_umount_developer(service_provider: LockdownClient):
72
- """ unmount Developer image """
80
+ """unmount Developer image"""
73
81
  try:
74
82
  DeveloperDiskImageMounter(lockdown=service_provider).umount()
75
- logger.info('Developer image unmounted successfully')
83
+ logger.info("Developer image unmounted successfully")
76
84
  except NotMountedError:
77
- logger.error('Developer image isn\'t currently mounted')
85
+ logger.exception("Developer image isn't currently mounted")
78
86
 
79
87
 
80
- @mounter.command('umount-personalized', cls=Command)
88
+ @mounter.command("umount-personalized", cls=Command)
81
89
  @catch_errors
82
90
  def mounter_umount_personalized(service_provider: LockdownClient):
83
- """ unmount Personalized image """
91
+ """unmount Personalized image"""
84
92
  try:
85
93
  PersonalizedImageMounter(lockdown=service_provider).umount()
86
- logger.info('Personalized image unmounted successfully')
94
+ logger.info("Personalized image unmounted successfully")
87
95
  except NotMountedError:
88
- logger.error('Personalized image isn\'t currently mounted')
96
+ logger.exception("Personalized image isn't currently mounted")
89
97
 
90
98
 
91
- @mounter.command('mount-developer', cls=Command)
92
- @click.argument('image', type=click.Path(exists=True, file_okay=True, dir_okay=False))
93
- @click.argument('signature', type=click.Path(exists=True, file_okay=True, dir_okay=False))
99
+ @mounter.command("mount-developer", cls=Command)
100
+ @click.argument("image", type=click.Path(exists=True, file_okay=True, dir_okay=False))
101
+ @click.argument("signature", type=click.Path(exists=True, file_okay=True, dir_okay=False))
94
102
  @catch_errors
95
103
  def mounter_mount_developer(service_provider: LockdownServiceProvider, image: str, signature: str) -> None:
96
- """ mount developer image """
104
+ """mount developer image"""
97
105
  DeveloperDiskImageMounter(lockdown=service_provider).mount(Path(image), Path(signature))
98
- logger.info('Developer image mounted successfully')
106
+ logger.info("Developer image mounted successfully")
99
107
 
100
108
 
101
- async def mounter_mount_personalized_task(service_provider: LockdownServiceProvider, image: str, trust_cache: str,
102
- build_manifest: str) -> None:
103
- await PersonalizedImageMounter(lockdown=service_provider).mount(Path(image), Path(build_manifest),
104
- Path(trust_cache))
105
- logger.info('Personalized image mounted successfully')
109
+ async def mounter_mount_personalized_task(
110
+ service_provider: LockdownServiceProvider, image: str, trust_cache: str, build_manifest: str
111
+ ) -> None:
112
+ await PersonalizedImageMounter(lockdown=service_provider).mount(
113
+ Path(image), Path(build_manifest), Path(trust_cache)
114
+ )
115
+ logger.info("Personalized image mounted successfully")
106
116
 
107
117
 
108
- @mounter.command('mount-personalized', cls=Command)
109
- @click.argument('image', type=click.Path(exists=True, file_okay=True, dir_okay=False))
110
- @click.argument('trust-cache', type=click.Path(exists=True, file_okay=True, dir_okay=False))
111
- @click.argument('build-manifest', type=click.Path(exists=True, file_okay=True, dir_okay=False))
118
+ @mounter.command("mount-personalized", cls=Command)
119
+ @click.argument("image", type=click.Path(exists=True, file_okay=True, dir_okay=False))
120
+ @click.argument("trust-cache", type=click.Path(exists=True, file_okay=True, dir_okay=False))
121
+ @click.argument("build-manifest", type=click.Path(exists=True, file_okay=True, dir_okay=False))
112
122
  @catch_errors
113
- def mounter_mount_personalized(service_provider: LockdownServiceProvider, image: str, trust_cache: str,
114
- build_manifest: str) -> None:
115
- """ mount personalized image """
123
+ def mounter_mount_personalized(
124
+ service_provider: LockdownServiceProvider, image: str, trust_cache: str, build_manifest: str
125
+ ) -> None:
126
+ """mount personalized image"""
116
127
  asyncio.run(mounter_mount_personalized_task(service_provider, image, trust_cache, build_manifest), debug=True)
117
128
 
118
129
 
119
130
  async def mounter_auto_mount_task(service_provider: LockdownServiceProvider, xcode: str, version: str) -> None:
120
131
  try:
121
132
  await auto_mount(service_provider, xcode=xcode, version=version)
122
- logger.info('DeveloperDiskImage mounted successfully')
133
+ logger.info("DeveloperDiskImage mounted successfully")
123
134
  except URLError:
124
- logger.warning('failed to query DeveloperDiskImage versions')
135
+ logger.warning("failed to query DeveloperDiskImage versions")
125
136
  except DeveloperDiskImageNotFoundError:
126
- logger.error('Unable to find the correct DeveloperDiskImage')
137
+ logger.exception("Unable to find the correct DeveloperDiskImage")
127
138
  except AlreadyMountedError:
128
- logger.error('DeveloperDiskImage already mounted')
139
+ logger.exception("DeveloperDiskImage already mounted")
129
140
  except PermissionError as e:
130
- logger.error(
131
- f'DeveloperDiskImage could not be saved to Xcode default path ({e.filename}). '
132
- f'Please make sure your user has the necessary permissions')
133
-
134
-
135
- @mounter.command('auto-mount', cls=Command)
136
- @click.option('-x', '--xcode', type=click.Path(exists=True, dir_okay=True, file_okay=False),
137
- help='Xcode application path used to figure out automatically the DeveloperDiskImage path')
138
- @click.option('--version', help='use a different DeveloperDiskImage version from the one retrieved by lockdown'
139
- 'connection')
141
+ logger.exception(
142
+ f"DeveloperDiskImage could not be saved to Xcode default path ({e.filename}). "
143
+ f"Please make sure your user has the necessary permissions"
144
+ )
145
+
146
+
147
+ @mounter.command("auto-mount", cls=Command)
148
+ @click.option(
149
+ "-x",
150
+ "--xcode",
151
+ type=click.Path(exists=True, dir_okay=True, file_okay=False),
152
+ help="Xcode application path used to figure out automatically the DeveloperDiskImage path",
153
+ )
154
+ @click.option(
155
+ "--version", help="use a different DeveloperDiskImage version from the one retrieved by lockdownconnection"
156
+ )
140
157
  def mounter_auto_mount(service_provider: LockdownServiceProvider, xcode: str, version: str) -> None:
141
- """ auto-detect correct DeveloperDiskImage and mount it """
158
+ """auto-detect correct DeveloperDiskImage and mount it"""
142
159
  asyncio.run(mounter_auto_mount_task(service_provider, xcode, version), debug=True)
143
160
 
144
161
 
145
- @mounter.command('query-developer-mode-status', cls=Command)
162
+ @mounter.command("query-developer-mode-status", cls=Command)
146
163
  def mounter_query_developer_mode_status(service_provider: LockdownClient):
147
- """ Query developer mode status """
164
+ """Query developer mode status"""
148
165
  print_json(MobileImageMounterService(lockdown=service_provider).query_developer_mode_status())
149
166
 
150
167
 
151
- @mounter.command('query-nonce', cls=Command)
152
- @click.option('--image-type')
168
+ @mounter.command("query-nonce", cls=Command)
169
+ @click.option("--image-type")
153
170
  def mounter_query_nonce(service_provider: LockdownClient, image_type: str):
154
- """ Query nonce """
171
+ """Query nonce"""
155
172
  print_json(MobileImageMounterService(lockdown=service_provider).query_nonce(image_type))
156
173
 
157
174
 
158
- @mounter.command('query-personalization-identifiers', cls=Command)
175
+ @mounter.command("query-personalization-identifiers", cls=Command)
159
176
  def mounter_query_personalization_identifiers(service_provider: LockdownClient):
160
- """ Query personalization identifiers """
177
+ """Query personalization identifiers"""
161
178
  print_json(MobileImageMounterService(lockdown=service_provider).query_personalization_identifiers())
162
179
 
163
180
 
164
- @mounter.command('query-personalization-manifest', cls=Command)
181
+ @mounter.command("query-personalization-manifest", cls=Command)
165
182
  def mounter_query_personalization_manifest(service_provider: LockdownClient):
166
- """ Query personalization manifest """
183
+ """Query personalization manifest"""
167
184
  result = []
168
185
  mounter = MobileImageMounterService(lockdown=service_provider)
169
186
  for device in mounter.copy_devices():
170
- result.append(mounter.query_personalization_manifest(device['PersonalizedImageType'], device['ImageSignature']))
187
+ result.append(mounter.query_personalization_manifest(device["PersonalizedImageType"], device["ImageSignature"]))
171
188
  print_json(result)
172
189
 
173
190
 
174
- @mounter.command('roll-personalization-nonce', cls=Command)
191
+ @mounter.command("roll-personalization-nonce", cls=Command)
175
192
  def mounter_roll_personalization_nonce(service_provider: LockdownClient):
176
193
  MobileImageMounterService(lockdown=service_provider).roll_personalization_nonce()
177
194
 
178
195
 
179
- @mounter.command('roll-cryptex-nonce', cls=Command)
196
+ @mounter.command("roll-cryptex-nonce", cls=Command)
180
197
  def mounter_roll_cryptex_nonce(service_provider: LockdownClient):
181
- """ Roll cryptex nonce (will reboot) """
198
+ """Roll cryptex nonce (will reboot)"""
182
199
  MobileImageMounterService(lockdown=service_provider).roll_cryptex_nonce()